Set
)Set<T>
Set<T>.prototype
:單一集合元素Set<T>.prototype
:所有集合元素Set<T>.prototype
:遍歷和迴圈Map
的對稱性.size
,而陣列有 .length
?在 ES6 之前,JavaScript 沒有集合的資料結構。取而代之的是,使用了兩個解決方法
自 ES6 起,JavaScript 有一個資料結構 Set
,它可以包含任意值,並快速執行成員檢查。
建立 Set 有三種常見的方式。
首先,你可以使用沒有任何參數的建構函數來建立一個空的 Set
const emptySet = new Set();
.equal(emptySet.size, 0); assert
其次,你可以將一個可迭代物件(例如陣列)傳遞給建構函數。可迭代物件的值會變成新 Set 的元素
const set = new Set(['red', 'green', 'blue']);
第三,.add()
方法會將元素加入 Set 中,而且可以串接使用
const set = new Set()
.add('red')
.add('green')
.add('blue');
.add()
會將一個元素加入 Set 中。
const set = new Set();
.add('red'); set
.has()
會檢查一個元素是否為 Set 的成員。
.equal(set.has('red'), true); assert
.delete()
會從 Set 中移除一個元素。
.equal(set.delete('red'), true); // there was a deletion
assert.equal(set.has('red'), false); assert
.size
包含 Set 中元素的數量。
const set = new Set()
.add('foo')
.add('bar');
.equal(set.size, 2) assert
.clear()
會移除 Set 中的所有元素。
.clear();
set.equal(set.size, 0) assert
Set 是可迭代的,而 for-of
迴圈會如你預期般運作
const set = new Set(['red', 'green', 'blue']);
for (const x of set) {
console.log(x);
}// Output:
// 'red'
// 'green'
// 'blue'
正如你所見,Set 會保留插入順序。也就是說,元素總是會按照它們被加入的順序進行迭代。
由於 Set 是可迭代的,你可以使用 Array.from()
將它們轉換成陣列
const set = new Set(['red', 'green', 'blue']);
const arr = Array.from(set); // ['red', 'green', 'blue']
將陣列轉換成 Set 再轉換回來,會從陣列中移除重複值
.deepEqual(
assertArray.from(new Set([1, 2, 1, 2, 3, 3, 3])),
1, 2, 3]); [
字串是可迭代的,因此可以用作 new Set()
的參數
.deepEqual(
assertnew Set('abc'),
new Set(['a', 'b', 'c']));
與 Map 鍵一樣,Set 元素的比較方式類似於 ===
,但例外情況是 NaN
等於它自己。
> const set = new Set([NaN, NaN, NaN]);
> set.size1
> set.has(NaN)true
與 ===
一樣,兩個不同的物件永遠不會被視為相等(而且目前沒有辦法改變這一點)
> const set = new Set();
> set.add({});
> set.size1
> set.add({});
> set.size2
Set 缺少一些常見的操作。這樣的操作通常可以透過以下方式實作
a
∪ b
)計算兩個 Set a
和 b
的聯集,表示建立一個包含 a
和 b
中所有元素的 Set。
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
// Use spreading to concatenate two iterables
const union = new Set([...a, ...b]);
.deepEqual(Array.from(union), [1, 2, 3, 4]); assert
a
∩ b
)計算兩個 Set a
和 b
的交集,表示建立一個包含 a
中也存在於 b
中的那些元素的 Set。
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
const intersection = new Set(
Array.from(a).filter(x => b.has(x))
;
)
.deepEqual(
assertArray.from(intersection), [2, 3]
; )
a
\ b
)計算兩個 Set a
和 b
的差集,表示建立一個包含 a
中不存在於 b
中的那些元素的 Set。這個操作有時也稱為減號(−)。
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
const difference = new Set(
Array.from(a).filter(x => !b.has(x))
;
)
.deepEqual(
assertArray.from(difference), [1]
; )
Set 沒有 .map()
方法。但我們可以借用陣列的
const set = new Set([1, 2, 3]);
const mappedSet = new Set(
Array.from(set).map(x => x * 2)
;
)
// Convert mappedSet to an Array to check what’s inside it
.deepEqual(
assertArray.from(mappedSet), [2, 4, 6]
; )
我們無法直接對 Set 執行 .filter()
,因此需要使用對應的陣列方法
const set = new Set([1, 2, 3, 4, 5]);
const filteredSet = new Set(
Array.from(set).filter(x => (x % 2) === 0)
;
)
.deepEqual(
assertArray.from(filteredSet), [2, 4]
; )
Set<T>
new Set<T>(values?: Iterable<T>)
[ES6]
如果您未提供參數 values
,則會建立一個空的 Set。如果您提供了,則會將迭代的值新增為 Set 中的元素。例如
const set = new Set(['red', 'green', 'blue']);
Set<T>.prototype
:單一 Set 元素.add(value: T): this
[ES6]
將 value
新增到此 Set。此方法會傳回 this
,這表示它可以串連。
const set = new Set(['red']);
.add('green').add('blue');
set.deepEqual(
assertArray.from(set), ['red', 'green', 'blue']
; )
.delete(value: T): boolean
[ES6]
從此 Set 中移除 value
。如果已刪除項目,則傳回 true
;否則傳回 false
。
const set = new Set(['red', 'green', 'blue']);
.equal(set.delete('red'), true); // there was a deletion
assert.deepEqual(
assertArray.from(set), ['green', 'blue']
; )
.has(value: T): boolean
[ES6]
檢查此 Set 中是否包含 value
。
const set = new Set(['red', 'green']);
.equal(set.has('red'), true);
assert.equal(set.has('blue'), false); assert
Set<T>.prototype
:所有 Set 元素get .size: number
[ES6]
傳回此 Set 中的元素數量。
const set = new Set(['red', 'green', 'blue']);
.equal(set.size, 3); assert
.clear(): void
[ES6]
從此 Set 中移除所有元素。
const set = new Set(['red', 'green', 'blue']);
.equal(set.size, 3);
assert.clear();
set.equal(set.size, 0); assert
Set<T>.prototype
:迭代和迴圈.values(): Iterable<T>
[ES6]
傳回此 Set 中所有元素的迭代器。
const set = new Set(['red', 'green']);
for (const x of set.values()) {
console.log(x);
}// Output:
// 'red'
// 'green'
[Symbol.iterator](): Iterable<T>
[ES6]
迭代 Set 的預設方式。與 .values()
相同。
const set = new Set(['red', 'green']);
for (const x of set) {
console.log(x);
}// Output:
// 'red'
// 'green'
.forEach(callback: (value: T, key: T, theSet: Set<T>) => void, thisArg?: any): void
[ES6]
將此 Set 的每個元素傳送至 callback()
。value
和 key
都包含目前的元素。引入此重複性,以便此 callback
具有與 Map.prototype.forEach()
的 callback
相同的類型簽章。
您可以透過 thisArg
指定 callback
的 this
。如果您省略它,this
會是 undefined
。
const set = new Set(['red', 'green']);
.forEach(x => console.log(x));
set// Output:
// 'red'
// 'green'
Map
的對稱性以下兩個方法主要存在,以便 Set 和 Map 具有類似的介面。每個 Set 元素都會處理為一個 Map 項目,其鍵和值都是該元素。
Set.prototype.entries(): Iterable<[T,T]>
[ES6]Set.prototype.keys(): Iterable<T>
[ES6].entries()
讓您可以將 Set 轉換為 Map
const set = new Set(['a', 'b', 'c']);
const map = new Map(set.entries());
.deepEqual(
assertArray.from(map.entries()),
'a','a'], ['b','b'], ['c','c']]
[[; )
.size
,而陣列有 .length
?此問題的解答請見 §33.6.4「為什麼 Map 有 .size
,而陣列有 .length
?」。
測驗
請參閱 測驗應用程式。