Javascript 集中的项目重复

Duplication of items in a Javascript Set

我正在学习 Javscript 的基础知识 Set.According 它的定义,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 有何不同?

尝试检查 {name: 'John'} === {name: 'John'}。你会发现它 returns 错误。

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


当您为变量分配引用值时,其内存位置将被复制。

例如:

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

因此,每次当您执行以下操作时:set.add(john);,您都在集合中添加内存位置。因此,Set 每次都会看到您添加 XYZ,并且不会接受重复项。

在第二种情况下, 当你这样做时:

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

因此,您的 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"}];