1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
---
title: Set
slug: Web/JavaScript/Reference/Global_Objects/Set
tags:
- Class
- ECMAScript6
- JavaScript
- set
- 全局对象
translation_of: Web/JavaScript/Reference/Global_Objects/Set
---
<div>{{ JSRef }}</div>
<p><strong><code>Set</code></strong> 对象允许你存储任何类型的唯一值,无论是{{ Glossary('Primitive', '原始值') }}或者是对象引用。</p>
<h2 id="简述">简述</h2>
<p><code>Set</code>对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会<strong>出现一次</strong>,即 Set 中的元素是唯一的。</p>
<h3 id="值的相等">值的相等</h3>
<p>因为 Set 中的值总是唯一的,所以需要判断两个值是否相等。在ECMAScript规范的早期版本中,这不是基于和===操作符中使用的算法相同的算法。具体来说,对于 Set s, +0 (+0 严格相等于-0)和-0是不同的值。然而,在 ECMAScript 2015规范中这点已被更改。有关详细信息,请参阅<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set#浏览器兼容性">浏览器兼容性</a> 表中的“<em>Key equality for -0 and 0</em>”。</p>
<p>另外,<code>NaN</code>和<code>undefined</code>都可以被存储在Set 中, <code>NaN</code>之间被视为相同的值(NaN被认为是相同的,尽管 NaN !== NaN)。</p>
<h2 id="Constructor">Constructor</h2>
<dl>
<dt><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set/Set"><code>Set()</code></a></dt>
<dd>创建一个新的<code>Set</code>对象。</dd>
</dl>
<h2 id="静态属性">静态属性</h2>
<dl>
<dt>{{jsxref("Set.@@species", "get Set[@@species]")}}</dt>
<dd>构造函数用来创建派生对象.</dd>
</dl>
<h2 id="Properties" name="Properties">实例属性</h2>
<dl>
<dt>{{jsxref("Set.prototype.size")}}</dt>
<dd>返回 Set 对象中的值的个数</dd>
</dl>
<h2 id="实例方法">实例方法</h2>
<dl>
<dt>{{jsxref("Set.add", "Set.prototype.add(<em>value</em>)")}}</dt>
<dd>在<code>Set</code>对象尾部添加一个元素。返回该<code>Set</code>对象。</dd>
<dt>{{jsxref("Set.prototype.clear()")}}</dt>
<dd>移除<code>Set</code>对象内的所有元素。</dd>
<dt>{{jsxref("Set.delete", "Set.prototype.delete(<em>value</em>)")}}</dt>
<dd>移除<code>Set</code>中与这个值相等的元素,返回<code>Set.prototype.has(value)</code>在这个操作前会返回的值(即如果该元素存在,返回<code>true</code>,否则返回<code>false</code>)。<code>Set.prototype.has(value)</code>在此后会返回<code>false</code>。</dd>
<dt>{{jsxref("Set.prototype.entries()")}}</dt>
<dd>返回一个新的迭代器对象,该对象包含<code>Set</code>对象中的按插入顺序排列的所有元素的值的<code>[value, value]</code>数组。为了使这个方法和<code>Map</code>对象保持相似, 每个值的键和值相等。</dd>
<dt>{{jsxref("Set.forEach", "Set.prototype.forEach(<em>callbackFn</em>[, <em>thisArg</em>])")}}</dt>
<dd>按照插入顺序,为Set对象中的每一个值调用一次callBackFn。如果提供了<code>thisArg</code>参数,回调中的<code>this</code>会是这个参数。</dd>
<dt>{{jsxref("Set.has", "Set.prototype.has(<em>value</em>)")}}</dt>
<dd>返回一个布尔值,表示该值在<code>Set</code>中存在与否。</dd>
<dt>{{jsxref("Set.prototype.keys()")}}</dt>
<dd>与<strong><code>values()</code></strong>方法相同,返回一个新的迭代器对象,该对象包含<code>Set</code>对象中的按插入顺序排列的所有元素的值。</dd>
<dt>{{jsxref("Set.prototype.values()")}}</dt>
<dd>返回一个新的迭代器对象,该对象包含<code>Set</code>对象中的按插入顺序排列的所有元素的值。</dd>
<dt>{{jsxref("Set.prototype.@@iterator()", "Set.prototype[@@iterator]()")}}</dt>
<dd>返回一个新的迭代器对象,该对象包含<code>Set</code>对象中的按插入顺序排列的所有元素的值。</dd>
</dl>
<h2 id="示例">示例</h2>
<h3 id="使用Set对象">使用<code>Set</code>对象</h3>
<pre class="brush: js">let mySet = new Set();
mySet.add(1); // Set [ 1 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add("some text"); // Set [ 1, 5, "some text" ]
let o = {a: 1, b: 2};
mySet.add(o);
mySet.add({a: 1, b: 2}); // o 指向的是不同的对象,所以没问题
mySet.has(1); // true
mySet.has(3); // false
mySet.has(5); // true
mySet.has(Math.sqrt(25)); // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true
mySet.size; // 5
mySet.delete(5); // true, 从set中移除5
mySet.has(5); // false, 5已经被移除
mySet.size; // 4, 刚刚移除一个值
console.log(mySet);
// logs Set(4) [ 1, "some text", {…}, {…} ] in Firefox
// logs Set(4) { 1, "some text", {…}, {…} } in Chrome</pre>
<h3 id="迭代Set">迭代Set</h3>
<pre class="brush: js">// 迭代整个set
// 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}
for (let item of mySet) console.log(item);
// 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}
for (let item of mySet.keys()) console.log(item);
// 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}
for (let item of mySet.values()) console.log(item);
// 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}
//(键与值相等)
for (let [key, value] of mySet.entries()) console.log(key);
// 使用 Array.from 转换Set为Array
var myArr = Array.from(mySet); // [1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}]
// 如果在HTML文档中工作,也可以:
mySet.add(document.body);
mySet.has(document.querySelector("body")); // true
// Set 和 Array互换
mySet2 = new Set([1, 2, 3, 4]);
mySet2.size; // 4
[...mySet2]; // [1,2,3,4]
// 可以通过如下代码模拟求交集
let intersection = new Set([...set1].filter(x => set2.has(x)));
// 可以通过如下代码模拟求差集
let difference = new Set([...set1].filter(x => !set2.has(x)));
// 用forEach迭代
mySet.forEach(function(value) {
console.log(value);
});
// 1
// 2
// 3
// 4
</pre>
<h3 id="实现基本集合操作">实现基本集合操作</h3>
<pre class="brush: js">function isSuperset(set, subset) {
for (let elem of subset) {
if (!set.has(elem)) {
return false;
}
}
return true;
}
function union(setA, setB) {
let _union = new Set(setA);
for (let elem of setB) {
_union.add(elem);
}
return _union;
}
function intersection(setA, setB) {
let _intersection = new Set();
for (let elem of setB) {
if (setA.has(elem)) {
_intersection.add(elem);
}
}
return _intersection;
}
<code>function symmetricDifference(setA, setB) {
let _difference = new Set(setA);
for (let elem of setB) {
if (_difference.has(elem)) {
_difference.delete(elem);
} else {
_difference.add(elem);
}
}
return _difference;
}</code>
function difference(setA, setB) {
let _difference = new Set(setA);
for (let elem of setB) {
_difference.delete(elem);
}
return _difference;
}
//Examples
let setA = new Set([1, 2, 3, 4]),
setB = new Set([2, 3]),
setC = new Set([3, 4, 5, 6]);
isSuperset(setA, setB); // => true
union(setA, setC); // => Set [1, 2, 3, 4, 5, 6]
intersection(setA, setC); // => Set [3, 4]
symmetricDifference(setA, setC); // => Set [1, 2, 5, 6]
difference(setA, setC); // => Set [1, 2]
</pre>
<h3 id="Array_相关"> <code>Array</code> 相关</h3>
<pre class="brush: js">let myArray = ["value1", "value2", "value3"];
// 用Set构造器将Array转换为Set
let mySet = new Set(myArray);
mySet.has("value1"); // returns true
// 用...(展开操作符)操作符将Set转换为Array
console.log([...mySet]); // 与myArray完全一致
</pre>
<h3 id="数组去重">数组去重</h3>
<pre class="brush: js">// Use to remove duplicate elements from the array
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
</pre>
<h3 id="String_相关"><code>String</code> 相关</h3>
<pre class="brush: js">let text = 'India';
let mySet = new Set(text); // Set {'I', 'n', 'd', 'i', 'a'}
mySet.size; // 5
// 大小写敏感 & duplicate ommision
new Set("Firefox") // Set(7) [ "F", "i", "r", "e", "f", "o", "x" ]
new Set("firefox") // Set(6) [ "f", "i", "r", "e", "o", "x" ]
</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">规范</th>
</tr>
<tr>
<td>{{ SpecName('ESDraft', '#sec-set-objects', 'Set') }}</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{ Compat('javascript.builtins.Set') }}</p>
<h2 id="参见">参见</h2>
<ul>
<li>{{ jsxref('Map') }}</li>
<li>{{ jsxref('WeakMap') }}</li>
<li>{{ jsxref('WeakSet') }}</li>
</ul>
|