es6中的map
含義:
Map的提出為了解決js中object(物件=>{key:value})中鍵(key)只能是字串的限制,Map的鍵(key)可以是各種型別的值(包括物件)都可以當作鍵(key),包括es6提出的Set
和Map
都可以用來生成新的 Map。
const m = new Map();
(1)如果對同一個鍵多次賦值,後面的值將覆蓋前面的值。
(2)如果讀取一個未知的鍵,則返回undefined
。
注意,只有對同一個物件的引用,Map 結構才將其視為同一個鍵。這一點要非常小心。(可以理解為,用物件名來新增或者獲取,不要用物件的例項來新增獲取)
例:
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
const k1 = ['a'];
const k2 = ['a'];
map
.set(k1, 111)
.set(k2, 222);
map.get(k1) // 111
map.get(k2) // 222
Map 的鍵實際上是跟記憶體地址繫結的,只要記憶體地址不一樣,就視為兩個鍵。這就解決了同名屬性碰撞(clash)的問題,我們擴充套件別人的庫的時候,如果使用物件作為鍵名,就不用擔心自己的屬性與原作者的屬性同名。在Map中0
和-0
就是一個鍵,布林值true
true
則是兩個不同的鍵。另外,undefined
和null
也是兩個不同的鍵。雖然NaN
不嚴格相等於自身,但 Map 將其視為同一個鍵。
屬性和操作方法
(1)size 屬性:size
屬性返回 Map 結構的成員總數
(2)set(key, value):set
方法設定鍵名key
對應的鍵值為value
,然後返回整個 Map 結構。如果key
已經有值,則鍵值會被更 新,否則就新生成該鍵。(set
Map
物件,因此可以採用鏈式寫法。)
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
(3)get(key):get
方法讀取key
對應的鍵值,如果找不到key
,返回undefined
。
(4)has(key):has
方法返回一個布林值,表示某個鍵是否在當前 Map 物件之中。
(5)delete(key):delete
方法刪除某個鍵,返回true
。如果刪除失敗,返回false
。
(6)clear():clear
方法清除所有成員,沒有返回值。
遍歷方法
keys()
:返回鍵名的遍歷器。values()
:返回鍵值的遍歷器。entries()
:返回所有成員的遍歷器。forEach()
:遍歷 Map 的所有成員。
注意:Map 的遍歷順序就是插入順序。
例:(下面的例子中最後兩種相等)
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同於使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
Map 結構轉為陣列結構,比較快速的方法是使用擴充套件運算子(...
)。
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
結合陣列的map
方法、filter
方法,可以實現 Map 的遍歷和過濾(Map 本身沒有map
和filter
方法)。
const map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
const map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
// 產生 Map 結構 {1 => 'a', 2 => 'b'}
const map2 = new Map(
[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 產生 Map 結構 {2 => '_a', 4 => '_b', 6 => '_c'}
此外,Map 還有一個forEach
方法,與陣列的forEach
方法類似,也可以實現遍歷。
const reporter = {
report: function(key, value) {
console.log("Key: %s, Value: %s", key, value);
}
};
map.forEach(function(value, key, map) {
this.report(key, value);
}, reporter);
上面程式碼中,forEach
方法的回撥函式的this
,就指向reporter
。
結構轉換
(1)Map 轉為陣列:...
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
(2)陣列 轉為 Map:將陣列寫入 Map 建構函式
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
(3)Map 轉為物件:如果所有 Map 的鍵都是字串,它可以無損地轉為物件。如果有非字串的鍵名,那麼這個鍵名會被轉成字串,再作為物件的鍵名。
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
(4)物件轉為 Map:
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}
(5)Map 轉為 JSON
Map 轉為 JSON 要區分兩種情況。一種情況是,Map 的鍵名都是字串,這時可以選擇轉為物件 JSON。
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
另一種情況是,Map 的鍵名有非字串,這時可以選擇轉為陣列 JSON。
unction mapToArrayJson(map) {
return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
(6)JSON 轉為 Map
JSON 轉為 Map,正常情況下,所有鍵名都是字串。
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
但是,有一種特殊情況,整個 JSON 就是一個數組,且每個陣列成員本身,又是一個有兩個成員的陣列。這時,它可以一一對應地轉為 Map。這往往是 Map 轉為陣列 JSON 的逆操作。
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}