es之Map

2,962 阅读3分钟

1、Map

Map数据结构

  • Map 类似于对象,也是键值对的集合,但是键名的范围不限制于字符串,各种类似的值(包括对象)都可以单作键。
  • Map参数可以是数组,任何具有iterator接口且每个成员都是一个双元素数组的数据结构。
  • Map遍历顺序是插入顺序

Object结构提供“字符串-值”的对应,Map结构提供“值-值”的对应。

var map = new Map([
    ['foo', 1],
    ['bar', 2]
]);

实例的属性

  • size
var map = new Map();

map.set({}, 'object');

map.size //1

实例的操作方法

  • set(key, value): Map
  • get(key): value | undefined
  • has(key): boolean
  • delete(key): boolean -clear(): void
var m = new Map();

//链式调用
m.set(undefined, 'un')
 .set(null, 'null')
 .set(NaN, 'nan')
 .set({}, 'object')
 .set({}, 'object')
 
m.size //5 

只有对同一个对象的引用,Map结构才将其视为同一个键,0和-0,NaN和NaN视为同一个键。对应基础类型数值只要严格相等就是同一个键。

map.get(NaN); //'nan'
map.get('name'); //undefined

map.has(NaN); //true
map.has('name'); //false

map.delele(NaN); //true
map.delete(NaN); //false

map.clear()

map.size //0

实例的遍历方法

  • keys()
  • values()
  • entries()
  • forEach()
var map = new Map([
    ['foo', 1],
    [undefined, 2],
]);

for(let item of map.keys()){
    console.log(item);
}
//'foo'
//undefined

for(let item of map.values()){
    console.log(item);
}
//1
//2

for(let item of map.entries()){
    console.log(item);
}
//['foo', 1]
//[undefined, 2]

for(let [key, value] of map.entries()){
    console.log([key, value]);
}
//['foo', 1]
//[undefined, 2]

map.forEach(function(value, key, map){
    //todo
}, this)

map直接进行遍历

for(let [key, value] of map){
    console.log([key, value]);
}
//['foo', 1]
//[undefined, 2]

与其他数据结构的相互转换

Map转数组

Map 与扩展运算符结合,转成数组,就可以使用数组的map()、filter()方法

var map = new Map([
    ['foo', 1],
    [undefined, 2],
]);

[...map.keys()]
//['foo', undefined]

[...map.values()]
//[1, 2]

[...map.entries()]或[...map]
//[['foo', 1], [undefined, 2]]

数组转Map

将数组传入Map 构造函数就可以转为Map

var map = new Map([
    ['foo', 1],
    [undefined, 2],
]);

Map转为对象

如果Map的所有键都是字符串,则可以转为对象

function strMapToObj(map){
    let obj = Object.creat(null);
    for(let [key, value] of map){
        obj[key] = value;
    }
    return obj;
}

var map = new Map([
    ['foo', 1],
    ['bar', 2],
]);
strMapToObj(map);
//{'foo': 1, 'bar': 2}

对象转为Map

function objMapToMap(obj){
    let map = new Map;
    for(let key of Object.keys(obj)){
        map.set(key, obj[key]);
    }
    return map;
}

var map = new Map([
    ['foo', 1],
    ['bar', 2],
]);
var obj = {'foo': 1, 'bar': 2};
objMapToMap(obj);
//Map {'foo'=> 1, 'bar' => 2}

Map转为Json

对于Map的键名都是字符串,这时候转成对象JSON

function strMapToJSON(strMap){
    return JSON.stringify(strMapToObj(strMap))
}

对于键名非字符串,这时转成数组JSON

function strMapToJSON(map){
    return JSON.stringify([...map])
}

JSON转为Map

对于所有键名都是字符串

function strJSONToMap(jsonStr){
    return objToStrMap(JSON.parse(jsonStr))
}

对于整个JSON就是一个数组,且每个数组成员本身又是一个具有两个成员的数组

function jsonToMap(jsonStr){
    return new Map(JSON.parse(jsonStr))
}

2、WeakMap

WeakMap区别于Map

  • 只接受对象作为键名(null除外),并且键名的引用是一种弱引用,不接受其他类型的值作为键名
  • 键名所指的对象不计入垃圾回收机制
  • 没有遍历操作(keys()、values()、entries()、forEach方法),也没有size属性,没有clear()方法
const element = document.getElementById('foo');

var map = new Map([
    [element, 'foo元素']
]);

实例的方法

  • set(): Map
  • get(): value
  • has(): boolean
  • delete(): boolean

注: 本文参照阮一峰老师的《ES6标准入门》而写的学习笔记