为何两段JavaScript Set添加对象的代码输出结果不同?
为何两段Set处理对象的代码输出结果不同?
你已经清楚JavaScript的Set通过引用地址(准确说是SameValueZero算法)判断对象是否重复,但这两段代码的差异根源不在对象引用,而是Set.add()方法的使用错误。
代码1的问题
代码1:
let list = [ {a:1,b:1},{a:2,b:3},{a:3,b:1} ] let set = new Set(list); let newList = [{a:1,b:2},{a:3,b:1}]; set.add(...newList) // 这里是错误用法 let newFilteredList = [...set] console.log(newFilteredList)
输出结果:
(4) [{...}, {...}, {...}, {...}] 0 : {a: 1, b: 1} 1 : {a: 2, b: 3} 2 : {a: 3, b: 1} 3 : {a: 1, b: 2}
核心原因
Set.prototype.add()仅接受单个参数,它的作用是向Set添加一个元素。你这里用展开运算符...newList,相当于给add传了两个参数,但add只会处理第一个参数{a:1,b:2},第二个参数{a:3,b:1}直接被忽略。最终Set里只有原3个元素加上新增的1个,共4个。
代码2的正确执行
代码2:
let list = [ {a:1,b:1},{a:2,b:3},{a:3,b:1} ] let newList = [{a:1,b:2},{a:3,b:1}]; let employees = [...list, ...newList] let set = new Set(employees) let newFilteredList = [...set] console.log(newFilteredList)
输出结果:
(5) [{...}, {...}, {...}, {...}, {...}] 0 : {a: 1, b: 1} 1 : {a: 2, b: 3} 2 : {a: 3, b: 1} 3 : {a: 1, b: 2} 4 : {a: 3, b: 1}
核心原因
这里先把list和newList合并成包含5个对象的数组employees,再用这个数组初始化Set。因为数组里的每个对象都是独立的引用(即使内容相同,两个{a:3,b:1}也是不同的对象实例),所以Set会保留全部5个元素。
补充:给Set添加多个元素的正确方式
如果要像代码1那样给已有Set添加多个元素,不能直接用add(...newList),应该遍历数组逐个添加:
// 方式1:遍历添加 newList.forEach(item => set.add(item)); // 方式2:用扩展运算符创建新Set set = new Set([...set, ...newList]);
内容的提问来源于stack exchange,提问作者Sadman Jahin
相关产品推荐
相关产品推荐

