集合
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Set
对象允许你存储任何类型的唯一值,无论是 primitive values 还是对象引用。
¥The Set
object lets you store unique values of any type, whether primitive values or object references.
描述
¥Description
Set
对象是值的集合。集合中的值只能出现一次;它在该系列的收藏中是独一无二的。你可以按插入顺序迭代集合的元素。插入顺序对应于 add()
方法成功将每个元素插入集合中的顺序(即,调用 add()
时集合中尚不存在相同的元素)。
¥Set
objects are collections of values. A value in the set may only occur once; it is unique in the set's collection. You can iterate through the elements of a set in insertion order. The insertion order corresponds to the order in which each element was inserted into the set by the add()
method successfully (that is, there wasn't an identical element already in the set when add()
was called).
该规范要求实现 "平均而言,提供的访问时间与集合中元素的数量呈次线性关系" 集。因此,它可以在内部表示为哈希表(具有 O(1) 查找)、搜索树(具有 O(log(N)) 查找)或任何其他数据结构,只要复杂度优于 O (N)。
¥The specification requires sets to be implemented "that, on average, provide access times that are sublinear on the number of elements in the collection". Therefore, it could be represented internally as a hash table (with O(1) lookup), a search tree (with O(log(N)) lookup), or any other data structure, as long as the complexity is better than O(N).
值相等性
¥Value equality
值相等基于 SameValueZero 算法。(以前使用 SameValue,将 0
和 -0
视为不同的。检查 浏览器兼容性。)这意味着 NaN
被认为与 NaN
相同(即使 NaN !== NaN
),并且根据 ===
运算符的语义,所有其他值都被认为是相等的。
¥Value equality is based on the SameValueZero algorithm. (It used to use SameValue, which treated 0
and -0
as different. Check browser compatibility.) This means NaN
is considered the same as NaN
(even though NaN !== NaN
) and all other values are considered equal according to the semantics of the ===
operator.
性能
¥Performance
has
方法检查某个值是否在集合中,所使用的方法平均而言比测试先前添加到集合中的大多数元素要快。特别是,当数组的 length
等于集合的 size
时,平均而言,它比 Array.prototype.includes
方法更快。
¥The has
method checks if a value is in the set, using an approach that is, on average, quicker than testing most of the elements that have previously been added to the set. In particular, it is, on average, faster than the Array.prototype.includes
method when an array has a length
equal to a set's size
.
设置构图
¥Set composition
Set
对象提供了一些方法,允许你像数学运算一样组合集合。这些方法包括:
¥The Set
object provides some methods that allow you to compose sets like you would with mathematical operations. These methods include:
方法 | 返回类型 | 数学等价 | 维恩图 |
---|---|---|---|
A.difference(B) |
Set |
||
A.intersection(B) |
Set |
||
A.symmetricDifference(B) |
Set |
||
A.union(B) |
Set |
||
A.isDisjointFrom(B) |
Boolean |
||
A.isSubsetOf(B) |
Boolean |
||
A.isSupersetOf(B) |
Boolean |
为了使它们更具通用性,这些方法不仅接受 Set
对象,还接受任何 set-like 对象。
¥To make them more generalizable, these methods don't just accept Set
objects, but anything that's set-like.
类似集合的对象
¥Set-like objects
所有 集合组合方法 都要求 this
是实际的 Set
实例,但它们的参数只需类似设置即可。类集合对象是提供以下功能的对象:
¥All set composition methods require this
to be an actual Set
instance, but their arguments just need to be set-like. A set-like object is an object that provides the following:
例如,Map
对象是类似集合的,因为它们也有 size
、has()
和 keys()
,因此在 set 方法中使用时它们的行为就像键集合:
¥For example, Map
objects are set-like because they also have size
, has()
, and keys()
, so they behave just like sets of keys when used in set methods:
const a = new Set([1, 2, 3]);
const b = new Map([
[1, "one"],
[2, "two"],
[4, "four"],
]);
console.log(a.union(b)); // Set(4) {1, 2, 3, 4}
注意:类似集合的协议调用
keys()
方法而不是[Symbol.iterator]()
来生成元素。这是为了使映射成为有效的类似集合的对象,因为对于映射,迭代器会生成条目,但has()
方法需要键。¥Note: The set-like protocol invokes the
keys()
method instead of[Symbol.iterator]()
to produce elements. This is to make maps valid set-like objects, because for maps, the iterator produces entries but thehas()
method takes keys.
数组 不像集合,因为它们没有 has()
方法或 size
属性,并且它们的 keys()
方法生成索引而不是元素。WeakSet
对象也不像集合,因为它们没有 keys()
方法。
¥Arrays are not set-like because they don't have a has()
method or the size
property, and their keys()
method produces indices instead of elements. WeakSet
objects are also not set-like because they don't have a keys()
method.
类似集合的浏览器 API
¥Set-like browser APIs
类似浏览器 Set
的对象(或 "类似集合的对象")是 Web API 接口,其行为在很多方面与 Set
类似。
¥Browser Set
-like objects (or "setlike objects") are Web API interfaces that behave in many ways like a Set
.
就像 Set
一样,元素可以按照添加到对象的顺序进行迭代。类似 Set
的对象和 Set
也具有共享相同名称和行为的属性和方法。然而,与 Set
不同的是,它们只允许每个条目使用特定的预定义类型。
¥Just like Set
, elements can be iterated in the same order that they were added to the object.
Set
-like objects and Set
also have properties and methods that share the same name and behavior.
However unlike Set
they only allow a specific predefined type for each entry.
允许的类型在规范 IDL 定义中设置。例如,GPUSupportedFeatures
是一个类似 Set
的对象,必须使用字符串作为键/值。这是在下面的 IDL 规范中定义的:
¥The allowed types are set in the specification IDL definition.
For example, GPUSupportedFeatures
is a Set
-like object that must use strings as the key/value.
This is defined in the specification IDL below:
interface GPUSupportedFeatures {
readonly setlike<DOMString>;
};
类似 Set
的对象要么是只读的,要么是可读写的(请参阅上面 IDL 中的 readonly
关键字)。
¥Set
-like objects are either read-only or read-writable (see the readonly
keyword in the IDL above).
- 类似
Set
的只读对象具有size
属性和方法:entries()
、forEach()
、has()
、keys()
、values()
和[Symbol.iterator]()
。 - 可写
Set
类对象还具有以下方法:clear()
、delete()
和add()
。
除了对条目类型的限制之外,方法和属性与 Set
中的等效实体具有相同的行为。
¥The methods and properties have the same behavior as the equivalent entities in Set
, except for the restriction on the types of the entry.
以下是类似 Set
的只读浏览器对象的示例:
¥The following are examples of read-only Set
-like browser objects:
以下是可写的类 Set
浏览器对象的示例:
¥The following are examples of writable Set
-like browser objects:
构造函数
静态属性
实例属性
¥Instance properties
这些属性在 Set.prototype
上定义并由所有 Set
实例共享。
¥These properties are defined on Set.prototype
and shared by all Set
instances.
Set.prototype.constructor
-
创建实例对象的构造函数。对于
Set
实例,初始值为Set
构造函数。 Set.prototype.size
-
返回
Set
对象中的值的数量。 Set.prototype[Symbol.toStringTag]
-
[Symbol.toStringTag]
属性的初始值为字符串"Set"
。该属性在Object.prototype.toString()
中使用。
实例方法
¥Instance methods
Set.prototype.add()
-
如果
Set
中没有具有相同值的元素,则将具有指定值的新元素插入到Set
对象中。 Set.prototype.clear()
-
从
Set
对象中删除所有元素。 Set.prototype.delete()
-
删除与
value
关联的元素并返回一个布尔值,断言元素是否已成功删除。之后Set.prototype.has(value)
将返回false
。 Set.prototype.difference()
-
获取一个集合并返回一个新集合,其中包含该集合中但不包含给定集合中的元素。
Set.prototype.entries()
-
返回一个新的迭代器对象,其中按插入顺序包含
Set
对象中每个元素的[value, value]
数组。这与Map
对象类似,因此每个条目的键与其Set
的值相同。 Set.prototype.forEach()
-
按插入顺序,对
Set
对象中存在的每个值调用callbackFn
一次。如果提供了thisArg
参数,它将用作每次调用callbackFn
时的this
值。 Set.prototype.has()
-
返回一个布尔值,断言
Set
对象中是否存在具有给定值的元素。 Set.prototype.intersection()
-
获取一个集合并返回一个新集合,其中包含该集合和给定集合中的元素。
Set.prototype.isDisjointFrom()
-
接受一个集合并返回一个布尔值,指示该集合是否没有与给定集合相同的元素。
Set.prototype.isSubsetOf()
-
接受一个集合并返回一个布尔值,指示该集合的所有元素是否都在给定集合中。
Set.prototype.isSupersetOf()
-
获取一个集合并返回一个布尔值,指示给定集合的所有元素是否都在该集合中。
Set.prototype.keys()
Set.prototype.symmetricDifference()
-
获取一个集合并返回一个新集合,其中包含位于该集合或给定集合中的元素,但不同时位于两者中。
Set.prototype.union()
-
获取一个集合并返回一个新集合,其中包含该集合和给定集合中的一个或两个中的元素。
Set.prototype.values()
-
返回一个新的迭代器对象,该对象按插入顺序生成
Set
对象中每个元素的值。 Set.prototype[Symbol.iterator]()
-
返回一个新的迭代器对象,该对象按插入顺序生成
Set
对象中每个元素的值。
示例
使用 Set 对象
¥Using the Set object
const mySet1 = new Set();
mySet1.add(1); // Set(1) { 1 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add("some text"); // Set(3) { 1, 5, 'some text' }
const o = { a: 1, b: 2 };
mySet1.add(o);
mySet1.add({ a: 1, b: 2 }); // o is referencing a different object, so this is okay
mySet1.has(1); // true
mySet1.has(3); // false, since 3 has not been added to the set
mySet1.has(5); // true
mySet1.has(Math.sqrt(25)); // true
mySet1.has("Some Text".toLowerCase()); // true
mySet1.has(o); // true
mySet1.size; // 5
mySet1.delete(5); // removes 5 from the set
mySet1.has(5); // false, 5 has been removed
mySet1.size; // 4, since we just removed one value
mySet1.add(5); // Set(5) { 1, 'some text', {...}, {...}, 5 } - a previously deleted item will be added as a new item, it will not retain its original position before deletion
console.log(mySet1); // Set(5) { 1, "some text", {…}, {…}, 5 }
迭代集
¥Iterating sets
集合上的迭代按插入顺序访问元素。
¥The iteration over a set visits elements in insertion order.
for (const item of mySet1) {
console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
for (const item of mySet1.keys()) {
console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
for (const item of mySet1.values()) {
console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
// key and value are the same here
for (const [key, value] of mySet1.entries()) {
console.log(key);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
// Convert Set object to an Array object, with Array.from
const myArr = Array.from(mySet1); // [1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}, 5]
// the following will also work if run in an HTML document
mySet1.add(document.body);
mySet1.has(document.querySelector("body")); // true
// converting between Set and Array
const mySet2 = new Set([1, 2, 3, 4]);
console.log(mySet2.size); // 4
console.log([...mySet2]); // [1, 2, 3, 4]
// intersect can be simulated via
const intersection = new Set([...mySet1].filter((x) => mySet2.has(x)));
// difference can be simulated via
const difference = new Set([...mySet1].filter((x) => !mySet2.has(x)));
// Iterate set entries with forEach()
mySet2.forEach((value) => {
console.log(value);
});
// 1
// 2
// 3
// 4
实现基本的集合操作
¥Implementing basic set operations
function isSuperset(set, subset) {
for (const elem of subset) {
if (!set.has(elem)) {
return false;
}
}
return true;
}
function union(setA, setB) {
const _union = new Set(setA);
for (const elem of setB) {
_union.add(elem);
}
return _union;
}
function intersection(setA, setB) {
const _intersection = new Set();
for (const elem of setB) {
if (setA.has(elem)) {
_intersection.add(elem);
}
}
return _intersection;
}
function symmetricDifference(setA, setB) {
const _difference = new Set(setA);
for (const elem of setB) {
if (_difference.has(elem)) {
_difference.delete(elem);
} else {
_difference.add(elem);
}
}
return _difference;
}
function difference(setA, setB) {
const _difference = new Set(setA);
for (const elem of setB) {
_difference.delete(elem);
}
return _difference;
}
// Examples
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 3]);
const setC = new Set([3, 4, 5, 6]);
isSuperset(setA, setB); // returns true
union(setA, setC); // returns Set {1, 2, 3, 4, 5, 6}
intersection(setA, setC); // returns Set {3, 4}
symmetricDifference(setA, setC); // returns Set {1, 2, 5, 6}
difference(setA, setC); // returns Set {1, 2}
与数组的关系
¥Relation to arrays
const myArray = ["value1", "value2", "value3"];
// Use the regular Set constructor to transform an Array into a Set
const mySet = new Set(myArray);
mySet.has("value1"); // returns true
// Use the spread syntax to transform a set into an Array.
console.log([...mySet]); // Will show you exactly the same Array as myArray
从数组中删除重复元素
与字符串的关系
使用集合来确保值列表的唯一性
规范
Specification |
---|
ECMAScript Language Specification # sec-set-objects |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also