You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Array原型正确扩展groupBy方法(含已有distinct实现)

如何将groupBy函数扩展为Array的原型方法

我已经实现了一个groupBy函数,现在想把它扩展成Array的原型方法,让数组可以直接调用myItems.groupBy(item => item.key)。目前已经有了Array的distinct扩展代码,请问怎么正确完成groupBy的扩展?

现有groupBy函数代码:

const groupBy = <T>(array: T[], predicate: (value: T, index: number, array: T[]) => string) =>
  array.reduce((acc, value, index, array) => {
    (acc[predicate(value, index, array)] ||= []).push(value);
    return acc;
  }, {} as { [key: string]: T[] });

已有Array扩展代码:

export { };
declare global {
    interface Array<T> {
        distinct(): Array<T>;
    }
}

if (!Array.prototype.distinct) {
    Array.prototype.distinct = function <T>(): T[] {
        const stringifiedItems = this.map((item) => JSON.stringify(item));
        const set = new Set(stringifiedItems);
        return Array.from(set).map((item) => JSON.parse(item));
    };
}

实现步骤

1. 扩展Array的全局类型声明

在全局Array<T>接口中添加groupBy方法的类型定义,和原函数的参数、返回值类型保持一致:

export { };
declare global {
    interface Array<T> {
        distinct(): Array<T>;
        // 添加groupBy的类型声明
        groupBy(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] };
    }
}

2. 实现groupBy原型方法

参照distinct的实现逻辑,先检查方法是否已存在(避免覆盖原生或第三方库的同名方法),再把原groupBy的逻辑迁移到原型方法中——这里的this就是当前调用的数组实例:

if (!Array.prototype.groupBy) {
    Array.prototype.groupBy = function <T>(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] } {
        return this.reduce((acc, value, index, array) => {
            const key = predicate(value, index, array);
            (acc[key] ||= []).push(value);
            return acc;
        }, {} as { [key: string]: T[] });
    };
}

完整整合代码

将两部分合并后的完整代码如下:

export { };
declare global {
    interface Array<T> {
        distinct(): Array<T>;
        groupBy(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] };
    }
}

// 实现distinct方法
if (!Array.prototype.distinct) {
    Array.prototype.distinct = function <T>(): T[] {
        const stringifiedItems = this.map((item) => JSON.stringify(item));
        const set = new Set(stringifiedItems);
        return Array.from(set).map((item) => JSON.parse(item));
    };
}

// 实现groupBy方法
if (!Array.prototype.groupBy) {
    Array.prototype.groupBy = function <T>(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] } {
        return this.reduce((acc, value, index, array) => {
            const key = predicate(value, index, array);
            (acc[key] ||= []).push(value);
            return acc;
        }, {} as { [key: string]: T[] });
    };
}

使用示例

现在可以按预期调用方法:

const myItems = [
    { key: 'a', value: 1 },
    { key: 'b', value: 2 },
    { key: 'a', value: 3 }
];

const grouped = myItems.groupBy(item => item.key);
// 输出:{ a: [{ key: 'a', value: 1 }, { key: 'a', value: 3 }], b: [{ key: 'b', value: 2 }] }

注意事项

  • 用if (!Array.prototype.groupBy)做存在性检查,防止意外覆盖已有方法
  • 保持泛型T和Array的泛型一致,保证类型安全
  • 原函数中的array参数对应原型方法里的this,迁移时注意替换

内容的提问来源于stack exchange,提问作者pianoman102

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:50:24