ES6 新增了 Map 物件,它在結構上和物件一樣是 key-value 的組合,不同的地方在於:
size
屬性能得到裡面的數量,物件沒有。// 建立空的 Map 物件
var map = new Map();
// 從既有的 iterable object (通常是陣列)建立 Map 物件
var map = new Map([iterable]);
Map 物件只能透過 Map constructor function 來建立,可以先建立空 Map 物件,再用set
方法加入,或從現有的 ”iterable object” 來建立。
JavaScript iterable object 是指可以被迭代的物件,簡單的判斷法是能夠被for..of
迴圈使用的物件,陣列是內建的 iterable object,通常會使用陣列來建立 Map。
建立 Map 的陣列需要一定格式,就是陣列項目必須是成對的,例如[[1, "one"], [2, "two"], [3, "three"]]
。Map 建構器會將第一個值當做 key,另一個當做 value。
大木博士的實驗室接受全世界訓練師寄放寶可夢,讓他有樣本可以做研究。同一個物種會有不同訓練師送過來,為了區別牠們,大木博士使用 Map 來建立資料庫,同時為每一隻寶可夢做追踪記錄。
const oaksLab = new Map();
// 訓練師們寄放寶可夢在研究室
const pokemon1 = {
name: "Pikachu",
trainer: "Ash",
};
const pokemon2 = {
name: "Pikachu",
trainer: "Gary",
};
const pokemon3 = {
name: "Psydock",
trainer: "Misty",
};
// 接收寶可夢時,博士會為每一隻的狀況做記錄
oaksLab.set(pokemon1, {
gender: "male",
age: 2
});
oaksLab.set(pokemon2, {
gender: "male",
age: 3
});
oaksLab.set(pokemon3, {
gender: "male",
age: 1
});
/*
oaksLab: Map {
{ name: 'Pikachu', trainer: 'Ash' } => { gender: 'male', age: 2 },
{ name: 'Pikachu', trainer: 'Gary' } => { gender: 'male', age: 3 },
{ name: 'Psydock', trainer: 'Misty' } => { gender: 'male', age: 1 }
}
*/
檢查 Map 物件能看到以上的對應關系,而第一組物件被當成 key 值,這在純物件是沒辦法做到的。
找尋特定的項目用get
,代入 key 值或者設立的變數名稱,會得到 value 的值。如果沒有這個項目會得到undefined
。
oaksLab.get(pokemon2);
// { gender: 'male', age: 3 }
oaksLab.get(pokemon4);
// undefined
檢查 Map 裡有多少組項目。
oaksLab.size;
// 3
使用has
檢查某個 key 是否存在。
oaksLab.has(pokemon1); // true
oaksLab.has(pokemon3); // true
oaksLab.has(pokemon4); // false
當寶可夢被領回去了,使用delete
刪除該項目。
oaksLab.delete(pokemon1);
oaksLab.size; // 2
oaksLab.has(pokemon1); // false
如果實驗室關閉了,博士把所有保管的寶可夢送回去,就用clear
把 Map 給清空。
oaksLab.clear();
oaksLab.size; // 0
Map 是迭代物件,可以用for..of
迴圈。
/*
oaksLab: Map {
{ name: 'Pikachu', trainer: 'Ash' } => { gender: 'male', age: 2 },
{ name: 'Pikachu', trainer: 'Gary' } => { gender: 'male', age: 3 },
{ name: 'Psydock', trainer: 'Misty' } => { gender: 'male', age: 1 }
}
*/
for(pokemon of oaksLab) {
console.log(pokemon);
}
// [ { name: 'Pikachu', trainer: 'Ash' }, { gender: 'male', age: 2 } ]
// [ { name: 'Pikachu', trainer: 'Gary' }, { gender: 'male', age: 3 } ]
// [ { name: 'Psydock', trainer: 'Misty' }, { gender: 'male', age: 1 } ]
每次迭代裡,會得到擁有二個項目的陣列,第一個項目是 key 值,第二個項目是 value 值。我們也可以用keys
和values
這二個方法來迭代 Map 裡的 key 和 value。
for(key of oaksLab.keys()) {
console.log(key);
}
// { name: 'Pikachu', trainer: 'Ash' }
// { name: 'Pikachu', trainer: 'Gary' }
// { name: 'Psydock', trainer: 'Misty' }
for(value of oaksLab.values()) {
console.log(value);
}
// { gender: 'male', age: 2 }
// { gender: 'male', age: 3 }
// { gender: 'male', age: 1 }
除了keys
和value
之外,還有一個 entries
方法,這三個方法回傳的值都是 iterator object,表示除了可以使用 for..of
迴圈之外,還可以用.next()
來分段執行,像 generator 一樣。
const entryIterator = oaksLab.entries();
entryIterator.next();
// { value: [ { name: 'Pikachu', trainer: 'Ash' }, { gender: 'male', age: 2 } ], done: false }
entryIterator.next();
// { value: [ { name: 'Pikachu', trainer: 'Gary' }, { gender: 'male', age: 3 } ], done: false }
entryIterator.next();
// { value: [ { name: 'Psydock', trainer: 'Misty' }, { gender: 'male', age: 1 } ], done: false }
entryIterator.next();
// { value: undefined, done: true }
const keyIterator = oaksLab.keys();
keyIterator.next();
// { value: { name: 'Pikachu', trainer: 'Ash' }, done: false }
keyIterator.next();
// { value: { name: 'Pikachu', trainer: 'Gary' }, done: false }
keyIterator.next();
// { value: { name: 'Psydock', trainer: 'Misty' }, done: false }
keyIterator.next();
// { value: undefined, done: true }
const valueIterator = oaksLab.values();
valueIterator.next();
// { value: { gender: 'male', age: 2 }, done: false }
valueIterator.next();
// { value: { gender: 'male', age: 3 }, done: false }
valueIterator.next();
// { value: { gender: 'male', age: 1 }, done: false }
valueIterator.next();
// { value: undefined, done: true }