Skip to main content

為什麼需要 Map?

Map 被引入之前,JavaScript 開發者主要使用 普通物件 (Plain Object) 來作為「鍵值對 (Key-Value Pair)」的對應表結構。然而,普通物件在擔任這個角色時有兩個主要的限制,這正是 ECMAScript 委員會決定創建 Map 的原因:

1. 繼承的原型屬性問題

每個 JavaScript 普通物件都會從它的原型 (Prototype) 繼承屬性。

  • 問題所在: 當您嘗試使用物件來儲存資料時,您可能會意外地讀取或覆蓋從原型鏈上繼承來的屬性,例如 toStringconstructor。這會導致資料上的命名衝突 (Name Collision)非預期的行為

  • 舉例說明: 即使您沒有明確地將鍵設定為 'toString',當您檢查 obj['toString'] 時,您仍會得到一個繼承來的函式,而不是您預期中的 undefined 或您自己的值。要避免這個問題,開發者必須使用像 Object.create(null) 來創建「空原型」的物件,或是使用 hasOwnProperty() 進行額外的檢查,非常麻煩。

2. 鍵的資料型態限制

普通物件只能使用 字串 (String)Symbol 作為鍵 (Key)

  • 問題所在:

    • 如果您使用數字 (Number)布林值 (Boolean) 或任何其他非字串的基本型態作為鍵,JavaScript 會自動將它們強制轉換 (Coerce) 成字串。例如,obj[5]obj['5'] 實際上是同一個鍵。

    • 更重要的限制是,您不能使用物件函式作為鍵。如果您嘗試這樣做,它們會被強制轉換成字串,例如 "[object Object]",這使得所有物件鍵都變成了同一個字串鍵,導致您無法區分不同的物件實例。

  • 舉例說明:

    let a = {id: 1};
    let b = {id: 2};
    let myObj = {};

    myObj[a] = 'Value A';
    myObj[b] = 'Value B';

    console.log(myObj); // 輸出:{ '[object Object]': 'Value B' }
    // myObj[a] 和 myObj[b] 實際上都是在設定名為 '[object Object]' 的同一個屬性!

Map 如何解決這些問題?

Map (正式名稱為 Map 物件) 是一種新的集合型態,它專門被設計來作為純粹的鍵值對應表,徹底解決了上述兩個限制:

1. 沒有原型繼承問題

  • Map 是一個獨立的資料結構,不會從任何原型繼承屬性。

  • 您儲存的每一個鍵值對都是 Map 專屬的,不會受到任何預設屬性 (如 toStringconstructor) 的干擾。這使得 Map 成為一個「乾淨」的對應表。

2. 任何資料型態都可以作為鍵

  • Map 允許您使用任何型態的值作為鍵,包括:

    • 物件 (Objects)

    • 函式 (Functions)

    • 數字 (Numbers)

    • 布林值 (Booleans)

    • nullundefined

  • 當您使用物件作為鍵時,Map 會區分不同的物件實例。這意味著您可以使用一個 DOM 元素或一個類別實例作為鍵,並將資料「附著」在它上面。

    let a = {id: 1};
    let b = {id: 2};
    let myMap = new Map();

    myMap.set(a, 'Value A'); // 'a' 物件本身是鍵
    myMap.set(b, 'Value B'); // 'b' 物件本身是另一個鍵

    console.log(myMap.get(a)); // 輸出:'Value A'
    console.log(myMap.get(b)); // 輸出:'Value B'
    console.log(myMap.size); // 輸出:2

結論

總而言之,Map 的設計目標是提供一個專門可靠的鍵值儲存機制,避免了普通物件作為對應表時的原型污染鍵型態限制

特性普通物件 (Plain Object)Map
鍵的型態只能是字串或 Symbol任何型態 (物件、函式、數字等)
原型繼承會繼承原型鏈上的屬性不會繼承,是乾淨的鍵值對應
鍵值計算必須手動計算或使用迴圈內建 size 屬性可直接取得
迭代順序數字鍵會優先排序依照鍵被插入的順序進行迭代

因此,在現代 JavaScript 開發中,如果您需要一個可靠的高性能的、並且需要使用非字串鍵的對應表,Map 已經成為首選的資料型態。