JS中使用Set为对象数组去重出现结果差异的原理咨询
原理说明
- JavaScript 中的 Set 去重使用的是 SameValueZero 相等判定规则,和
===运算的逻辑基本一致,仅对NaN的判定有差异(Set 会认为两个NaN是相等的)。 - 你遇到的差异本质是引用类型和值类型的判定规则不同:对象属于引用类型,相等判断比较的是内存引用地址,而非对象内部的属性值。
两个案例的差异解释
- 第一个数组
arr中的三个对象是独立声明的对象字面量,每一个都会在堆内存中开辟独立的存储空间,对应的引用地址完全不同。就算三个对象的属性名、属性值完全一致,在 Set 判定时也会被识别为三个不同的值,因此最终 Set 长度为 3,没有去重效果。 - 第二个数组
sameArr中的三个元素都是同一个obj对象的引用,指向同一块内存地址,Set 判定时会认为是同一个值,因此去重后长度为 1。
常见对象数组去重方案
如果你需要根据对象内容去重,可以根据场景选择以下方案:
按指定属性组合去重
适合明确知道要以哪几个属性作为去重判定依据的场景,性能更稳定:
// 以 type 和 power 组合作为去重依据 const uniqueMap = new Map() arr.forEach(item => { const key = `${item.type}-${item.power}` if (!uniqueMap.has(key)) { uniqueMap.set(key, item) } }) const uniqueArr = Array.from(uniqueMap.values())
全属性序列化去重
适合结构简单、属性顺序一致的普通对象,注意该方案会丢失属性值为 undefined、Function、Symbol 的内容,循环引用的对象也会报错:
const uniqueArr = Array.from(new Set(arr.map(item => JSON.stringify(item)))) .map(str => JSON.parse(str))
内容的提问来源于stack exchange,提问作者PCPbiscuit
相关产品推荐
相关产品推荐

