跳至主要内容

Map()

資訊

此篇適合:正在學習 JavaScript 的人

Map 是什麼

Map 是 JavaScript ES6 新增的資料結構,用來儲存「鍵值對 (Key-Value pairs)」的集合。與一般物件不同,Map 的 key 可以是任何型別(字串、數字、物件、函式等),而不只是字串。

Map 與 Object 的差異

特性MapObject
Key 的型別可以是任何型別只能是字串或 Symbol
大小使用 .size 取得需手動計算
迭代順序依照插入順序ES6+ 有順序,但較複雜
預設屬性無預設屬性有原型鏈屬性
效能頻繁增刪時較好較適合靜態資料

Map 怎麼用?

建立 Map

// 建立空的 Map
const myMap = new Map();

// 或建立時就帶入初始值(陣列包陣列格式)
const myMap2 = new Map([
['name', 'Alice'],
['age', 25],
[1, 'number key'],
]);

從物件建立 Map

如果原始資料是物件,需要使用 Object.entries() 將物件轉換成「陣列包陣列」的格式:

// 原始資料
const obj = {
name: 'Alice',
age: 25,
city: 'Taipei'
};

// 轉換成陣列包陣列
const myMap = new Map(Object.entries(obj));
console.log(myMap);
// Map(3) { 'name' => 'Alice', 'age' => 25, 'city' => 'Taipei' }

基本操作

方法用途範例連結
.set(key, value)新增或更新鍵值對範例
.get(key)取得對應的值範例
.has(key)檢查 key 是否存在範例
.delete(key)刪除指定的鍵值對範例
.clear()清空所有鍵值對範例
.size取得 Map 的大小範例
.forEach() / for...of / .entries()遍歷所有鍵值對範例
.keys()取得所有 key範例
.values()取得所有 value範例

set

.set(key, value) - 新增或更新鍵值對

const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 25);
myMap.set(1, 'number key'); // key 可以是數字
myMap.set({ id: 1 }, 'object key'); // key 可以是物件

console.log(myMap);
// Map(4) { 'name' => 'Alice', 'age' => 25, 1 => 'number key', { id: 1 } => 'object key' }

get

.get(key) - 取得對應的值

const myMap = new Map();
myMap.set('name', 'Alice');

console.log(myMap.get('name')); // 'Alice'
console.log(myMap.get('notExist')); // undefined

has

.has(key) - 檢查 key 是否存在

const myMap = new Map();
myMap.set('name', 'Alice');

console.log(myMap.has('name')); // true
console.log(myMap.has('age')); // false

delete

.delete(key) - 刪除指定的鍵值對

const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 25);

myMap.delete('name');
console.log(myMap.has('name')); // false

clear

.clear() - 清空所有鍵值對

const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 25);

myMap.clear();
console.log(myMap.size); // 0

size

.size - 取得 Map 的大小

const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 25);

console.log(myMap.size); // 2

迭代 Map

foreach

遍歷所有鍵值對 - .forEach() / for...of / .entries()

這三種方式都能遍歷 Map 的所有鍵值對,結果相同,但使用上有差異:

方式特點使用時機
.forEach()方法調用,無法使用 break/continue簡單遍歷,不需要中斷控制
for...of (直接遍歷)語法結構,可使用 break/continue需要中斷或跳過某些元素
.entries()明確指定迭代器,等同於直接遍歷程式碼可讀性優先時使用

.forEach() - 方法調用

const myMap = new Map([
['name', 'Alice'],
['age', 25],
]);

myMap.forEach((value, key) => {
console.log(key, value);
});
// name Alice
// age 25

for...of - 直接遍歷(預設使用 entries)

const myMap = new Map([
['name', 'Alice'],
['age', 25],
]);

for (const [key, value] of myMap) {
console.log(key, value);
}
// name Alice
// age 25

.entries() - 明確使用迭代器(等同於直接遍歷)

const myMap = new Map([
['name', 'Alice'],
['age', 25],
]);

for (const [key, value] of myMap.entries()) {
console.log(key, value);
}
// name Alice
// age 25
提示

一般情況下使用 for...of 直接遍歷即可,因為:

  • 語法簡潔:for (const [key, value] of myMap)
  • 可以使用 break/continue 控制流程
  • 效能與 .entries() 相同(Map 的預設迭代器就是 entries)

keys

.keys() - 取得所有 key

const myMap = new Map([
['name', 'Alice'],
['age', 25],
]);

for (const key of myMap.keys()) {
console.log(key);
}
// name
// age

values

.values() - 取得所有 value

const myMap = new Map([
['name', 'Alice'],
['age', 25],
]);

for (const value of myMap.values()) {
console.log(value);
}
// Alice
// 25

實際應用場景

  1. 計數器
const countWords = (words) => {
const wordCount = new Map();

words.forEach(word => {
wordCount.set(word, (wordCount.get(word) || 0) + 1);
});

return wordCount;
};

const words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
console.log(countWords(words));
// Map(3) { 'apple' => 3, 'banana' => 2, 'orange' => 1 }
  1. 快取機制
const cache = new Map();

const getCachedData = (key) => {
if (cache.has(key)) {
return cache.get(key);
}

// 模擬取得資料
const data = `Data for ${key}`;
cache.set(key, data);
return data;
};

練習題

試著練習看看吧~

LeetCode(easy) - Two Sum

備註

以上內容為個人的理解,如果有什麼想法也歡迎留言跟我分享,讓我可以學習更多。

看更多: 解題思路