ES6为我们提供了Map数据结构。它是一个”value-value”的对应。如果需要“键值对”的数据结构,Map是一个很合适的数据结构。
Map
用法
简单用法
var map = new Map();
map.set('name','zxguan');
map.set('age',27);
map.get('name');
map.get('age');
通过console.log(map);
打印出的结果为:Map { 'name' => 'zxguan', 'age' => 27 }
数组作为构造参数
Map接受一个数组作为构造函数的参数。该数组的成员是一个个表示键值对的数组。
var map = new Map([['name','zxguan'],['age','27']]);
console.log(map);
结果一样也是:Map { 'name' => 'zxguan', 'age' => 27 }
以上的代码实际上等同于:
var map = new Map();
[['name','zxguan'],['age','27']].forEach(([key,value]) => map.set(key,value));
迭代
有以下方法来遍历一个Map:
- keys()返回所有的键名
- values()返回所有的值
- entries()返回所有的成员实体
- forEach()遍历Map所有的成员
代码:
var map = new Map([['name','zxguan'],['age','27']]);
var keys = map.keys(); //遍历Key
for(let key of keys){
console.log(key);
}
var values = map.values(); //遍历Value
for(let value of values){
console.log(value);
}
var entries = map.entries();//遍历实体
for(let [key,value] of entries){
console.log(key,value);
}
map.forEach((value,index)=>{//value为值,index实际上就是key
console.log("key:"+index + " value:"+value);
});
var reporter = {
report: function(key, value) {
console.log("Key: %s, Value: %s", key, value);
}
};
map.forEach(function(value, key, map) { //forEach的第二个方法用来绑定this.
this.report(key, value);
}, reporter);
常用的方法
- map.clear():clear方法清除所有成员,没有返回值。
- map.delete(key):删除键为key的成员。删除成功,返回true;删除失败,返回false。
- map.entries():返回所有的成员实体。
- forEach(callback):遍历Map所有的成员。
- get(key):读取key对应的键值,如果找不到key,返回undefined。
- has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
- keys():返回所有的键名。
- set(key,value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新建一个成员。
- size属性:属性返回Map结构的成员总数。
- values():返回所有的值。
值得注意的是,只有对同一个对象的引用,Map才会视为同一个key。如:
var map = new Map();
map.set(['KEY'],5);
var value = map.get(['KEY']);
console.log(value); //undefined
var key1 = ['KEY'];
var key2 = ['KEY'];
var map = new Map();
map.set(key1,'AAA');
map.set(key2,'BBB');
console.log(map.get(key1)); //AAA
console.log(map.get(key2)); //BBB
如果要将Map转换为数组,可以使用扩展运算符(…)
var myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
console.log([...myMap]);
以下是一些常用的转换工具方法:
//Map转Object对象
function map2Obj(map) {
let obj = {};
for (let [key, value] of map) {
obj[key] = value;
}
return obj;
}
//Object对象转Map
function obj2Map(obj) {
let map = new Map();
for (let key of Object.keys(obj)) {
map.set(key, obj[key]);
}
return map;
}
//Map转为Json
function map2Json(map) {
let keys = map.keys();
let isAllKeyStr = true; //是否key全部为字符串
for(let key of keys){
if(!((typeof key=='string')&&(key.constructor==String))){
isAllKeyStr = false;
break;
}
}
if(isAllKeyStr){
return JSON.stringify(map2Obj(map));
}else{
return JSON.stringify([...map]);
}
}
//Json转为Map
function json2Map(json) {
let _json = JSON.parse(json);
if(Array.isArray(_json)){
return new Map(JSON.parse(json));
}else{
return obj2Map(JSON.parse(json));
}
}
WeakMap
WeakMap与Map大体上是类似的,只有在以下方面有所区别:
- 只接受Object(对象)作为键名(null除外),不接受基本类型作为键值。
- WeakMap没有keys()、values()、entries()方法,也没有size属性
- WeakMap没有clear()方法