在 JavaScript 中,集合是一种类似列表的数据结构,其中只能包含唯一的原始值和/或对象引用。
集合必须用集合构造函数来创建;把一个数组传给构造函数,就能用其中的值来初始化它。
const emptySet = new Set();
const setWithInitialValues = new Set(['hello', 'world']);
如果一个值与集合中任意一个元素严格相等,就无法把它添加到这个集合里。
const set = new Set();
set.add(10);
set.add(10); // 10 is strictly equal to 10, so it can't be added again
set.size;
//=> 1;
set.has(10);
//=> true
set.delete(10);
//=> true; 10 was removed
set.delete(10);
//=> false; 10 is not in the set, so nothing happened
const obj = { color: 'magenta' };
const eerilySimilarObj = { color: 'magenta' };
set.add(obj);
set.add(eerilySimilarObj); // obj and eerilySimilarObj reference different objects, so they can both be added
set.size;
//=> 2
set.clear();
set.size;
//=> 0
用集合构造函数可以把数组转换成集合。用展开语法或Array.from()则可以把集合转换成数组。
const arrayWithDuplicates = [7, 3, 3, 9, 3];
const arrayWithoutDuplicates = [...new Set(arrayWithDuplicates)]; // [7, 3, 9]
const anotherArrayWithoutDuplicates = Array.from(new Set(arrayWithDuplicates)); // [7, 3, 9]
集合是一种键控集合,这意味着它的元素以键来索引,并且可以按插入顺序遍历。由于集合元素的_键_和_值_是同一个东西,所以Set.keys()和Set.values()可以互换使用。
const apples = ['Granny Smith', 'Honey Crisp', 'Royal Gala'];
const appleSet = new Set(apples);
for (let apple of appleSet.keys()) {
console.log(apple);
}
// 'Granny Smith'
// 'Honey Crisp'
// 'Royal Gala'
for (let apple of appleSet.values()) {
console.log(apple);
}
// 'Granny Smith'
// 'Honey Crisp'
// 'Royal Gala'
for (let apple of appleSet.entries()) {
console.log(apple);
}
// ['Granny Smith', 'Granny Smith']
// ['Honey Crisp', 'Honey Crisp']
// ['Royal Gala', 'Royal Gala']
当选择用集合(而不是数组)来存储一组数据时,通常是因为存储的值需要唯一。不过,既然用数组也能保证唯一性,那这么做的好处就不那么明显了。
简单的回答是:集合针对查找做了优化,而数组没有。数组的查找方法(例如Array.indexOf())的运行时间会随数组大小线性增长;也就是说,数组包含的元素越多,查找它所花的时间就越长。而集合的查找方法则具有恒定的运行时间,也就是说,无论集合有多大,查找时间都保持不变。
不过在实际情况中,除非数据量极其庞大,否则这种性能差异可以忽略不计。