JavaScript的對象本質上是鍵值的集合(Hash結構),只能用字符串做爲鍵。給使用帶來了很大的限制。javascript
const data = {}
const element = document.getElementById("mydiv")
data[element] = 'metadata'
data['[object HTMLDivElement]'] //"metadata"
複製代碼
爲了解決這個問題,ES6提供可Map結構。相似於對象,也是鍵值的結合,可是鍵的限制範圍再也不只是字符串,各類類型包括對象均可以看成鍵。Map提供了「值---值」對應,是一種更加完善的Hash結構,若是須要鍵值對的數據結構,Map比Object更加適合。java
const m = new Map()
const o = {p:"hello"}
m.set(o,'content')
m.get(o) // "content"
m.has(o) //true
m.delete(o) // true
m.has(o) // false
複製代碼
Map也能夠接受一個數組做爲參數,該數組成員是一個個表示鍵值對的數組算法
const map = new Map([
['name','zhangsan'],
['title','auther']
])
map.size //2
map.has('name') //true
map.get('name') //"zhangsan"
複製代碼
Map 構造函數接受數組做爲參數,其實是執行了下邊的算法:json
const items = [
['name','zhangsan'],
['title','auther']
]
const map = new Map()
items.forEach(
([value,key]) => map.set(key,value)
);
複製代碼
不單單是數組,任何具備 iterator 接口,且每一個成員都是一個雙元素數組的數據結構,均可以看成Map構造函數的參數,Set 和 Map 均可以用來生成新的Map。數組
注意:只有同一個鍵的引用,Map結構纔會將其視爲同一個鍵。數據結構
const map = new Map();
map.set(['a'],555);
map.get(['a']); // undefined
複製代碼
上面set和get表面上針對了同一個鍵,可是其實是兩個值,內存地址是不同的,所以get 沒法讀取該鍵。函數
若是Map的鍵是一個簡單類型(數字,字符串,布爾值),只要兩個值嚴格相等,Map就會將其視爲一個鍵,包括 0 -0,另外,雖然NaN不嚴格等於自身,可是Map將其視爲一個鍵。ui
返回map結構的成員總數this
set方法設置key所對應的鍵值,而後返回整個Map結構。若是key已經存在,則鍵值會被更新,不然新生成該鍵。spa
get 獲取 key 對應的鍵值,若是找不到 key,返回undefined。
has返回一個布爾值,表示某個鍵是否在Map結構中
delete刪除某個鍵,返回true,刪除失敗返回false
清除全部成員,沒有返回值。
一共3個遍歷器生成函數和1個遍歷方法
注意:Map的遍歷順序就是插入順序。
const map = new Map([
['f','no'],
['t','yes']
])
for(let key of map.keys()) {
}
for(let key of map.values()) {
}
for(let key of map.entries()) {
}
for(let [key,value] of map.entries()) {
}
// 等同於使用 map.entries()
for(let [key,value] of map) {
}
複製代碼
Map 結構轉爲數組結構比較快速的方法是 擴展運算符(...)
const map = new Map([
['f','no'],
['t','yes']
])
[...map.keys()] // ['f','t']
[...map.values()] //['no','yes']
[...map.entries()] // [['f','no'],['t','yes']]
[...map] // [['f','no'],['t','yes']]
複製代碼
結合數組的map方法,filter方法,實現Map結構的遍歷和過濾
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 map1 = new Map(
[...map0].map(([k,v]) => [k*2,'_' + v])
)
// Map {2 => '_a', 4 => '_b', 6 => '_c'}
複製代碼
Map 還有一個forEach方法,於數組的forEach類似
map.forEach(function(value,key,map) {
console.log("Key: %s, Value: %s",key,value)
})
複製代碼
forEach 能夠接受第二個參數,用來綁定this
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)
複製代碼
(...map)
new Map([
[true,7],
[{foo:3},['abc']]
])
複製代碼
若是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)
複製代碼
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轉JSON分兩種狀況,一種是 鍵名都是字符串,這時能夠轉化爲對象JSON
function strMapToJson(strMap){
return JSON.stringify(strMapToObj(strMap))
}
let map = new Map().set(['yes',true]).set(['no',false])
strMapToJson(map)
//'{"yes":true,"no":false}'
複製代碼
另外一種,Map鍵名不是字符串,轉化爲數組JSON
function mapToArrayJson(map) {
return JSON.stringify([...map])
}
let map = new Map().set(['yes',true]).set([{foo:3},[a,c,b]])
mapToArrayJson(map)
// '[['yes',true],[{foo:3},[a,c,b]]]'
複製代碼
function jsonToStrMap(josnStr) {
return objToStrMap(JSON.parse(jsonStr))
}
jsonToStrMap('{"yes":true,"no":false}')
// Map {'yes' => true, 'no' => false}
複製代碼