Map
對象保存鍵值對,並且能夠記住鍵的原始插入順序。任何值(對象或者原始值) 都可以作爲一個鍵或一個值。
一個Map對象在迭代時會根據對象中元素的插入順序來進行 — 一個 for...of
循環在每次迭代後會返回一個形式爲[key,value]的數組。
- 鍵的比較是基於
sameValueZero
算法: NaN
是與NaN
相等的(雖然NaN !== NaN
),剩下所有其它的值是根據===
運算符的結果判斷是否相等。- 在目前的ECMAScript規範中,
-0
和+0
被認爲是相等的,儘管這在早期的草案中並不是這樣。有關詳細信息,請參閱瀏覽器兼容性 表中的“Value equality for -0 and 0”。
Map與普通對象的區別:
Map | Object | |
---|---|---|
意外的鍵 |
|
一個 注意: 雖然 ES5 開始可以用 |
鍵的類型 | 一個 Map 的鍵可以是任意值,包括函數、對象或任意基本類型。 |
一個Object 的鍵必須是一個 String 或是Symbol 。 |
鍵的順序 |
|
一個 注意:自ECMAScript 2015規範以來,對象確實保留了字符串和Symbol鍵的創建順序; 因此,在只有字符串鍵的對象上進行迭代將按插入順序產生鍵。 |
Size | const map = new Map(); |
先轉換爲數組,然後獲取數組長度, |
迭代 |
|
迭代一個 必須將它們轉換爲數組,如使用 |
性能 | 在頻繁增刪鍵值對的場景下表現更好。 |
在頻繁添加和刪除鍵值對的場景下未作出優化。 |
let myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
let otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number" 雖然NaN!==NaN
遍歷:
let myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (let [key, value] of myMap) {
console.log(key + " = " + value);
}
// 將會顯示兩個log。一個是"0 = zero"另一個是"1 = one"
for (let key of myMap.keys()) {
console.log(key);
}
// 將會顯示兩個log。 一個是 "0" 另一個是 "1"
for (let value of myMap.values()) {
console.log(value);
}
// 將會顯示兩個log。 一個是 "zero" 另一個是 "one"
for (let [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
// 將會顯示兩個log。 一個是 "0 = zero" 另一個是 "1 = one"
Map
和Set
有何不同
Map
的行爲和Set
非常相似,並且它們都包含一些相同的方法,包括:has、get、set、delete。它們兩者都是鍵控集合,就是說你可以使用像forEach
的方法來遍歷元素,順序是按照插入鍵值排列的。
最大的不同是Map
通過鍵值(key/value)成對出現,就像你可以把一個數組轉換爲Set
,你也可以把二維數組轉換爲Map
:
const set = new Set([1, 2, 3, 4]);
const map = new Map([['one', 1], ['two', 2], ['three', 3], ['four', 4]]);
類型轉換:
要將Map
切換回數組,你可以使用ES6的解構語法:
const map = new Map([['one', 1], ['two', 2]]);
const arr = [...map];
map對象和常規對象互換:
const mapToObj = map => {
const obj = {};
map.forEach((key, value) => { obj[key] = value });
return obj;
};
const objToMap = obj => {
const map = new Map();
Object.keys(obj).forEach(key => { map.set(key, obj[key]) });
return map;
};
ES2019的首次展示中,我們看見了Object
引入了2個新方法:Object.entries()
和Object.fromEntries()
,這可以使上述方法簡化許多:
const obj2 = Object.fromEntries(map);
const map2 = new Map(Object.entries(obj));
其他:
請注意!爲Map設置對象屬性也是可以的,但是可能引起大量的混亂。
所以,你還是可以這樣做...
let wrongMap = new Map()
wrongMap['bla'] = 'blaa'
wrongMap['bla2'] = 'blaaa2'
console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' }
...但是,這樣做的話,它的行爲會不符合預期:
wrongMap.has('bla') // false
wrongMap.delete('bla') // false
console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' }
無論如何,和正確用法比較起來,幾乎沒有什麼不同:
let myMap = new Map()
myMap.set('bla','blaa')
myMap.set('bla2','blaa2')
console.log(myMap) // Map { 'bla' => 'blaa', 'bla2' => 'blaa2' }
myMap.has('bla') // true
myMap.delete('bla') // true
console.log(myMap) // Map { 'bla2' => 'blaa2' }