Map
Map 物件
一個 Map 物件是一個鍵值對映,它可以按插入順序迭代其元素。
以下程式碼展示了 Map 的一些基本操作。另請參閱 Map 參考頁面以獲取更多示例和完整的 API。你可以使用 for...of 迴圈為每次迭代返回一個 [key, value] 陣列。
const sayings = new Map();
sayings.set("dog", "woof");
sayings.set("cat", "meow");
sayings.set("elephant", "toot");
sayings.size; // 3
sayings.get("dog"); // woof
sayings.get("fox"); // undefined
sayings.has("bird"); // false
sayings.delete("dog");
sayings.has("dog"); // false
for (const [key, value] of sayings) {
console.log(`${key} goes ${value}`);
}
// "cat goes meow"
// "elephant goes toot"
sayings.clear();
sayings.size; // 0
Object 和 Map 的比較
傳統上,物件一直用於將字串對映到值。物件允許你將鍵設定為值、檢索這些值、刪除鍵以及檢測某個鍵是否儲存了內容。然而,Map 物件有一些額外的優勢,使它們成為更好的對映。
Object的鍵是字串或符號,而Map的鍵可以是任何值。- 你可以輕鬆獲取
Map的size,而對於Object,你必須手動跟蹤大小。 - Map 的迭代是按照元素的插入順序進行的。
- 一個
Object有一個原型,所以對映中存在預設鍵。(這可以透過使用map = Object.create(null)來繞過。)
這三個提示可以幫助你決定使用 Map 還是 Object
- 當鍵在執行時未知時,以及當所有鍵的型別相同且所有值的型別相同時,使用 Map 而不是物件。
- 如果需要將原始值作為鍵儲存,請使用 map,因為物件將每個鍵都視為字串,無論是數字值、布林值還是任何其他原始值。
- 當存在對單個元素進行操作的邏輯時,使用物件。
WeakMap 物件
一個 WeakMap 是一個鍵值對的集合,其鍵必須是物件或未註冊的符號,值可以是任何任意的JavaScript 型別,並且它不會對其鍵建立強引用。也就是說,物件作為 WeakMap 中的鍵存在並不會阻止該物件被垃圾回收。一旦用作鍵的物件被回收,它在任何 WeakMap 中對應的所有值也會成為垃圾回收的候選者——只要它們沒有被其他地方強引用。唯一可以作為 WeakMap 鍵的原始型別是符號——更具體地說,是未註冊的符號——因為未註冊的符號保證是唯一的,並且不能被重新建立。
WeakMap 的 API 與 Map 的 API 基本相同。然而,WeakMap 不允許觀察其鍵的活躍性,這就是它不允許列舉的原因。因此,沒有方法可以獲取 WeakMap 中鍵的列表。如果存在,該列表將取決於垃圾回收的狀態,從而引入不確定性。
有關更多資訊和示例程式碼,另請參閱 WeakMap 參考頁面上的“為什麼選擇 WeakMap?”。
WeakMap 物件的一個用例是儲存物件的私有資料,或隱藏實現細節。在以下示例中,私有資料和方法屬於物件內部,並存儲在 privates 物件中,該物件是一個 WeakMap。例項和原型上公開的一切都是公共的;其他一切都無法從外部訪問,因為 privates 未從模組匯出。
const privates = new WeakMap();
export default function Public() {
const me = {
// Private data goes here
};
privates.set(this, me);
}
Public.prototype.method = function () {
const me = privates.get(this);
// Do stuff with private data in `me`
// …
};
注意: 此用例現在可以透過類和私有欄位實現。
Set
Set 物件
Set 物件是唯一值的集合。你可以按插入順序迭代其元素。Set 中的一個值只能出現一次;它在 Set 集合中是唯一的。
以下程式碼展示了 Set 的一些基本操作。另請參閱 Set 參考頁面以獲取更多示例和完整的 API。
const mySet = new Set();
mySet.add(1);
mySet.add("some text");
mySet.add("foo");
mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2
for (const item of mySet) {
console.log(item);
}
// 1
// "some text"
Array 和 Set 之間的轉換
你可以使用 Array.from 或展開語法從 Set 建立一個 Array。此外,Set 建構函式接受一個 Array 進行反向轉換。
注意: Set 物件儲存唯一值——因此在轉換時,Array 中的任何重複元素都會被刪除!
Array.from(mySet);
[...mySet2];
mySet2 = new Set([1, 2, 3, 4]);
Array 和 Set 的比較
傳統上,在許多情況下,元素集合在 JavaScript 中儲存在陣列中。然而,Set 物件有一些優勢
- 按值刪除 Array 元素 (
arr.splice(arr.indexOf(val), 1)) 非常慢。 Set物件允許你按值刪除元素。對於陣列,你必須根據元素的索引進行splice操作。- 在陣列中無法使用
indexOf找到值NaN。 Set物件儲存唯一值。你無需手動跟蹤重複項。
WeakSet 物件
WeakSet 物件是可垃圾回收值的集合,包括物件和未註冊的符號。WeakSet 中的一個值只能出現一次。它在 WeakSet 集合中是唯一的。
與 Set 物件的主要區別在於
- 與
Set不同,WeakSet僅是物件或符號的集合,而不是任何型別的任意值的集合。 WeakSet是*弱引用*的:對集合中物件的引用是弱持有的。如果對儲存在WeakSet中的物件沒有其他引用,它們就可以被垃圾回收。這也意味著集合中沒有儲存當前物件的列表。WeakSet不可列舉。
WeakSet 物件的用例是有限的。它們不會造成記憶體洩漏,因此安全地使用 DOM 元素作為鍵並標記它們以進行跟蹤等目的會很有用。
Map 和 Set 的鍵值相等性
Map 物件的鍵相等性和 Set 物件的值相等性均基於 SameValueZero 演算法
- 相等性類似於全等比較運算子
===。 -0和+0被認為是相等的。NaN被認為與自身相等(與===相反)。