javascript数组精准去重关键在于明确定义“重复”:用object.is正确处理nan和±0,用类型+字符串化键区分1与"1",对象数组需按字段及类型双重校验,避免隐式转换或json.stringify陷阱。

JavaScript 数组去重若只依赖 === 或 Set,会遇到类型混淆问题:比如数字 1 和字符串 "1" 被视为不同,而 NaN === NaN 为 false 导致无法去重;对象因引用不同也被全量保留。要实现“精准去重”,关键不是单纯删重复值,而是明确定义“什么才算真正重复”——即结合值与类型双重判断。
用 Object.is 实现严格值+类型等价判断
Object.is() 是 JS 中最贴近“数学相等”的比较方法,它能正确处理 NaN === NaN(返回 true),且区分 +0 与 -0,同时保持对基本类型和字面量的严格类型感知。
- 适用于需要保留
NaN唯一性、区分0符号、避免字符串/数字误判的场景 - 不能直接用于
Set或indexOf,需配合filter或reduce
示例:
const arr = [1, "1", 0, -0, NaN, NaN, null, undefined];const unique = arr.filter((item, i) =>
arr.findIndex(v => Object.is(v, item)) === i
);
// 结果:[1, "1", 0, NaN, null, undefined]
// 注意:-0 被保留在 0 之后(因 Object.is(0, -0) === false)
手动构建类型敏感的哈希键
对每个元素生成「类型 + 字符串化内容」组合键,例如:typeof item + '|' + JSON.stringify(item)。这样可让 1 和 "1" 生成不同键,NaN 经 JSON.stringify(NaN) 得 "null"(需额外处理),而对象也能按结构比对(浅层)。
- 适合需要统一处理混合类型、又不想引入第三方库的中等复杂度场景
- 注意:
JSON.stringify无法序列化函数、undefined、Symbol、循环引用;对new Date()、RegExp等也表现异常
安全简化版(仅覆盖常见基础类型和简单对象):
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
if (val === null) return 'null|';
if (Number.isNaN(val)) return 'number|NaN';
const type = typeof val;
if (type === 'object' && Array.isArray(val)) {
return `array|${JSON.stringify(val)}`;
}
if (type === 'object') {
return `object|${JSON.stringify(val)}`;
}
return `${type}|${String(val)}`;
}
const arr = [1, "1", NaN, NaN, {a:1}, {a:1}];
const seen = new Set();
const unique = arr.filter(item => {
const key = getTypeKey(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
对象数组按字段 + 类型双重校验去重
业务中最常见的是用户、商品等对象列表按 id 去重,但若后端返回的 id 类型不一致(如字符串 "123" 和数字 123 混用),仅用 id 做 Set 判断会出错。此时应显式指定字段类型预期。
- 例如:强制将
id转为字符串再比对,或要求必须为数字并做Number()校验后判isNaN - 避免用
==或隐式转换,防止"0"、""、false被误判为相同
示例(强类型 id 字段):
const users = [{ id: 1, name: 'Alice' },
{ id: "1", name: 'Bob' }, // 类型不同,视为不同项
{ id: 2, name: 'Charlie' }
];
const uniqueUsers = users.filter((user, i, arr) => {
return arr.findIndex(u =>
u.id === user.id && typeof u.id === typeof user.id
) === i;
});
// 保留全部三项,因 id 类型不一致
避开陷阱:哪些“看似精准”其实不可靠
有些写法表面看兼顾了类型,实则存在隐蔽缺陷:
-
用
==或+隐式转换:如arr.indexOf(+item),会让"1"、true、1全部坍缩为1,失去类型精度 -
依赖
JSON.stringify处理所有对象:忽略属性顺序({a:1,b:2}≠{b:2,a:1})、丢失函数和原型方法、对Date输出为字符串而非原始值 -
未处理
undefined/null在对象键中的行为:用obj[item] = true时,undefined和null都会被转成字符串"undefined"和"null",导致冲突
真正精准,是让“重复”的定义清晰、可控、可测试。不需要追求一步到位的万能函数,而应在具体业务中明确:“这里谁和谁算重复?”——然后选择匹配的判断逻辑。










