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}
复制代码