Map与Set一样,也是ES6中新引入的数据结构,来切入正题。。。
我会从这几个方面来聊下Map数据结构:
1、传统对象(Object)缺点
2、Map数据结构基本用法
3、Map结构的实例属性和操作方法
4、Map结构的遍历方法
5、Map与数组、对象、JSON互相转换
1、传统对象( Object )缺点:
传统的JavaScript的对象(Object),本质上是键值对的集合,但是传统上只能用字符串当做键。这对于它的使用带来很大的不便!
2、Map基本用法:
为了解决传统对象的问题,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是" 键 "的范围不限于字符串,各种类型的值(包括对象),都可以当做键。
传统的对象是 :字符串 --------对应 --------值
而Map数据结构是 :值--------对应 -------- 值
eg:
let map = new Map()
let o = {name:"lxc",age:20};
map.set(o,"value")
map.get(o) //"value"
console.log(map)
map.has(o) //true
map.delete(o) // true
map.has(o) // false
//上边代码,只能用对应的索引作为键,不能用一个对象作为键
//因为下边两个对象是两个地址,而上边o是引用的额一个地址
let map = new Map();
map.set({name:"lxc"},"value")
console.log(map.get({name:"lxc"}))//undefined
打印结果:
上边代码:用set()方法,把对象作为键,用get()方法去读取这个键,用has()方法判断是否有这个键,接着删除键,对Map数据结构中的成员进行增删查操作。
Map也可以接受数组作为参数,数组的成员是一个个表示键值对的数组:
let map = new Map([["name","lxc"]]);
console.log(map)//Map(1) {"name" => "lxc"}
事实上不仅仅是数组,任何具有Iterator接口、并且每个成员是双元素数组的数据结构,都可以当做Map构造函数的参数。
关于Map数据结构中键我们再来详细看下:
<1> 上边我们已经说过,将 引用值 当做 " 键 " 时,不可以将引用值直接放到 "键"上,需要把引用值绑定到变量上,用变量充当 引用值的 "键"。
let map = new Map();
map.set({name:"lxc",age:20},"value")
console.log(map.get({name:"lxc"}))//undefined
上边代码的set和get,表面上看是针对的同一个键,但实际上两个键(对象)是不相等的,因为内存地址不一样,因此get方法无法读取键的值,所以返回undefined。。。
总结:实际上Map的键是跟内存地址绑定的,只要内存地址不一样,就视为两个键,
3、Map结构的实例属性和操作方法:
<1> size : 属性返回Map结构的成员总数(与set方法一致)
< 2 > Map . prototype . set ( key , value ) : 设置键名key对应的键值 value , 返回的是整个Map结构。
let map = new Map();
map.set("string","value") //key是字符串类型的
map.set(1,"value")// key是数字类型的
map.set(undefined,"value") // key是 undefined
set方法返回的是一个Map结构,因此可以链式操作(与Set数据结构中的add()方法一样,都可以链式操作)
let map = new Map();
map.set("string","value")
.set(1,"value")
.set(undefined,"value")
< 3 > Map . prototype . get ( key ) : 获取key对应的 值,如果找不到key,返回undefined。
< 4 > Map . prototype . has( key ) : 该方法返回一个布尔值,表示某个键是否在当前Map对象中。
< 5 > Map . prototype . delete( key ) : 删除某个键,返回true,如果删除失败,则返回false。
< 6 > Map . prototype . clear( ) : 清除所有成员,没有返回值
以上方法,与Set数据结构中的方法相同,这里就不一一举例了。。。
4、Map结构的遍历方法:
Map结构原生提供了三个遍历器生成函数和一个遍历方法。
Map.prototype.keys( ) : 返回键名的遍历器。
let map = new Map([["name","lxc"],["age","20"]]);
console.log(map.keys())//MapIterator {"name", "age"}
for(let items of map.keys()){
console.log(items) //name age
}
Map.prototype.values( ) : 返回键值的遍历器。
let map = new Map([["name","lxc"],["age","20"]]);
console.log(map.values())//MapIterator {"lxc", "20"}
for(let items of map.values()){
console.log(items) //"lxc" "20"
}
Map.prototype.entried( ) : 返回所有成员的遍历器。
let map = new Map([["name","lxc"],["age","20"]]);
console.log(map.entries())//MapIterator {"name" => "lxc", "age" => "20"}
for(let items of map.entries()){
console.log(items) //["name","lxc"] ["age","20"]
}
Map.prototype.forEach ( ) : 遍历Map的所有成员。
let map = new Map([["name","lxc"],["age","20"]]);
map.forEach((value,key)=>{
console.log(value) //"lxc" "20"
console.log(key) //"name" "age"
})
5、Map结构与其他数据互相转换:
(1)Map转为数组:用扩展运算符( ... )是最方便的方法。
let map = new Map([["name","lxc"],["age","20"]]);
console.log([...map.keys()]) //键组成一个数组 ["name","age"]
console.log([...map.values()]) //值组成一个数组 ["lxc","20"]
console.log([...map.entries()])// [["name","lxc"],["age","20"]]
console.log([...map])// [["name","lxc"],["age","20"]]
(2)数组转Map:将数组作为Map参数即可。
let res = new Map([[1,2]])
console.log(res) //Map(1) {1 => 2}
(3)Map转为对象:
将Map转化为对象,下边代码之所以用Object.create(null)来创建一个对象,而不是直接创建一个空对象,因为:用Object.create( null )来创建的对象,不会去继承对象原型上的任何属性、方法,当然你也可放心大胆的去用for···in循环,因为你再也不用担心遍历出原型上的属性了。
//向Set结构中添加
let map = new Map()
map.set("yes",true);
map.set("no",false);
function objFn(param){
let object = Object.create(null);
//结构赋值:[key,value] = ["yes",true]
//结构赋值:[key,value] = ["no",false]
for( let [key,value] of param ){
object[key] = value;
}
return object //{yes: true, no: false}
}
objFn(map);
(4)对象转Map:
大致思路是:遍历有个对象的属性key,用Map结构中的set ( )方法,向Map结构中插入数据。
let obj = {name:"lxc",age:20};
function createMap(obj){
let newMap = new Map();
//Object.keys()返回的是一个数组
for( let key of Object.keys(obj) ){
newMap.set(key,obj[key])
}
return newMap; //Map(2) {"name" => "lxc", "age" => 20}
}
createMap(obj);
(5)Map转JSON:
let map = new Map([["name","lxc"],["height","20"]]);
function mapToJson(map){
let obj = Object.create(null);
//还是一样在,下边是解构赋值,将key和value值依次拿出来
for( let [key,value] of map ){
obj[key] = value
}
return JSON.stringify(obj) //{"name":"lxc","height":"20"}
}
mapToJson(map);
(6)JSON转Map:
正常情况下,使用JSON.parse将JSON先转为对象,然后对象在转化为Map,但是有一种特殊情况,整个JSON是一个数组,数组里又是有两个成员的数组,这时,可以一一对应转为Map。
function jsonToMap(jsonStr){
return new Map(JSON.parse(jsonStr));
}
console.log ( jsonToMap('[["age",20],[{"name":"lxc"},["1"]]]') );
//Map(2) {"age" => 20, {…} => Array(1)}