JavaScript中Array.prototype.distinct非原生方法,不推荐污染原型链以防冲突和维护问题;若必须添加,应通过Object.defineProperty设置enumerable: false;更推荐工具函数、静态类方法或Set/Map等替代方案。

JavaScript 中 Array.prototype.distinct 并不是原生方法,不能直接使用。你需要手动在 Array.prototype 上添加该方法,但需注意:**不推荐污染原生原型链**,更推荐用工具函数或扩展类的方式实现去重。
为什么不要直接扩展 Array.prototype
向原生原型添加方法可能引发以下问题:
- 与其他库(如 Lodash、jQuery)或未来 JS 标准新增的同名方法冲突
- 影响
for...in遍历(虽可用Object.defineProperty设置enumerable: false缓解) - 降低代码可维护性与团队协作清晰度
安全添加 distinct 方法(如必须扩展)
若项目规范允许且明确知晓风险,可这样定义(兼容基本类型和简单对象):
Object.defineProperty(Array.prototype, 'distinct', {
value: function (key) {
if (key === undefined) {
// 基本类型去重(利用 Set)
return [...new Set(this)];
}
// 对象数组按指定 key 去重
const seen = new Set();
return this.filter(item => {
const val = typeof item === 'object' && item !== null ? item[key] : item;
if (seen.has(val)) return false;
seen.add(val);
return true;
});
},
writable: true,
configurable: true,
enumerable: false // 关键:避免被 for...in 遍历到
});
使用示例:
[1, 2, 2, 3].distinct(); // [1, 2, 3]
[{id: 1}, {id: 2}, {id: 1}].distinct('id'); // [{id: 1}, {id: 2}]
更推荐的替代方案
避免修改原生原型,推荐以下方式:
-
独立工具函数:如
const distinct = (arr, key) => { ... },导入即用 -
静态类方法:如
ArrayUtils.distinct(arr, 'id') -
ES6 扩展运算符 + Set(基础类型):
[...new Set(arr)] -
Map 去重对象数组:
Array.from(new Map(arr.map(v => [v.id, v])).values())
注意事项
去重逻辑取决于数据类型:
- 字符串、数字等原始值:
Set足够可靠 - 对象或嵌套结构:需深比较,建议用
JSON.stringify(仅限简单可序列化对象)或专用库(如 Lodash 的uniqBy) - NaN 和
0/-0:Set认为NaN === NaN(正确),但0 === -0(ES6 行为,通常可接受)











