重學ES6 Map

含義和基本用法

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

實例屬性和操做方法

size 屬性

返回map結構的成員總數this

set(key,value)

set方法設置key所對應的鍵值,而後返回整個Map結構。若是key已經存在,則鍵值會被更新,不然新生成該鍵。spa

get(key)

get 獲取 key 對應的鍵值,若是找不到 key,返回undefined。

has(key)

has返回一個布爾值,表示某個鍵是否在Map結構中

delete(key)

delete刪除某個鍵,返回true,刪除失敗返回false

clear()

清除全部成員,沒有返回值。

遍歷方法

一共3個遍歷器生成函數和1個遍歷方法

  • keys() 返回鍵名
  • values() 返回鍵值
  • entries() 返回全部成員
  • forEach() 遍歷map全部成員

注意: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轉爲數組

(...map)

數組轉Map

new Map([
    [true,7],
    [{foo:3},['abc']]
])
複製代碼

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)
複製代碼

對象轉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轉JSON

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]]]'
複製代碼

JSON轉Map

function jsonToStrMap(josnStr) {
    return objToStrMap(JSON.parse(jsonStr))
}
jsonToStrMap('{"yes":true,"no":false}')
// Map {'yes' => true, 'no' => false}
複製代碼
相關文章
相關標籤/搜索