在一个Javascript集中复制项目

问题描述 投票:0回答:1

我正在学习Javscript Set的基础知识,根据其定义。Set是一个特殊的类型集合--"值的集合"(没有键),每个值只能出现一次。

但我看到当涉及到引用类型时,行为是不同的。请看下面的片段。

let set = new Set();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);
console.log("Scenario 1");
for (let user of set) {
  console.log(user.name);
}

let set1 = new Set();
set1.add({ name: "John" });
set1.add({ name: "Pete" });
set1.add({ name: "Mary" });
set1.add({ name: "John" });
console.log("Scenario 2");
for (let user of set1) {
  console.log(user.name);
}

我看到在场景1中,它不允许重复添加,因为它们是相同的引用。但在场景2中,我看到重复的引用被添加了。

可以解释一下这种行为吗?或者说我是不是漏掉了什么。

方案1和方案2有什么不同?

javascript ecmascript-6 set ecmascript-5
1个回答
1
投票

A Set不看对象本身的内容。它只看对象的指针。

如果它不是同一个物理对象的指针,那么就允许把它作为不同的物理对象添加到Set中。事实上,你可以将一个对象添加到集合中,然后再改变它的内容,因为它在集合中的事实与对象的内容无关,只与对象的物理指针有关。如果不是同一个对象的指针,那么可以单独添加。

这里有一个例子。

let s = new Set();
let x1 = {name: "John"};
let x2 = {name: "John"};

console.log(x1 === x2);    // false, not the same physical object

s.add(x1);
console.log(s.has(x1));    // true
console.log(s.has(x2));    // false
s.add(x2);
console.log(s.has(x2));    // true
console.log(Array.from(s));      // [{name: "John"}, {name: "John"}];

// now modify x1
x1.name = "Bob";
// the x1 object is still in the set, even though you modified it
// because being in the set has NOTHING to do with the contents of the object at all
console.log(s.has(x1));    // true
console.log(Array.from(s));   // [{name: "Bob"}, {name: "John"}];

1
投票

试着检查一下 {name: 'John'} === {name: 'John'}. 你会发现它返回false。

每一个新的对象都有一个不同的引用,即使内容可能是一样的。如果它给你的是false,那么 Set 会认为它也是一个不同的元素。


当你给一个变量分配一个Reference值时,它的内存位置会被复制。

比如说,当你用Reference值分配变量时,它的内存位置会被复制。

let john = {name: 'John'} // lets say memory: XYZ

所以,每次当你做: set.add(john);,你都会在集合中添加内存位置。所以,集会看到你添加了 XYZ 每次都不接受重复的内容。

在第二种情况下,当你做。

`set1.add({ name: "John" });` // You added maybe XYF
`set1.add({ name: "John" });` // You added maybe XYN

所以,你的 "集 "会区别对待,把它们都加进去。

© www.soinside.com 2019 - 2024. All rights reserved.