ES6新特性-Map和WeakMap

参考文档:MDN

Map结构

在Javascript中,对象是以键值对的方式存在的,其中的键名是以字符串或者数值以及ES6提出的新的数据类型Symbol方式存在的,比如下面:

let m = {
    k: 1,
    2: 4
}

m.k; // 1
m[2]; //4

但是无法使用引用类型数据作为键名:

const body = document.getElementsByTagName('body')[0];

let m = {};

m.k = 1;
m[body] = 4;

m; // {k: 1, [object HTMLBodyElement]: 4}

m['[object HTMLBodyElement]']; // 4


/*
    从这里看出来其实当我们用DOM对象作为m属性的时候,
    实际上并没有把DOM对象作为键名,而是通过把DOM对象
    toString()方法的返回字符串值当作了键名。
*/

ES6提出了一种新的结构来解决引用类型作为键值不能实现的问题。Map类型,Map类型可以使用任意数据类型作为键值。Map类型常用的方法及属性有以下几种:

Map.prototype.size:返回Map对象的键值对

Map.prototype.clear():移除Map结构中所有的键值对

Map.prototype.delete(key):移除key键,成功返回true,反之false

Map.prototype.get(key):或者key键的值,如果不存在返回undefined

Map.prototype.set(key, value):设置Map键值。key作为键,value作为键值

Map.prototype.has(key):查找是否在当前Map结构中存在key键,返回true和false

当然还有其他和Set结构一样的方法没有列举出来,如果想见全部方法,大家可以到MDN文档查看。

Map是一个构造函数,可以接受一个参数,此参数是数组,此数组的成员为键值对或者两个元素的数组,每个元素或者键值对会被添加到Map结构中,null为undefined。

let tmp = [['name', 'tom'],['age', 18]];
const m = new Map(tmp); 

m.get('name'); //'tom'
m.get('age'); // 18

使用引用类型当键值

const body = document.getElementsByTagName('body')[0];

const m = new Map();

m.set(body, 'this is body'); 

m.get(body); // 'this is body'

这里需要注意的一点是引用类型是指的是变量名其实存储的是一个内存地址,并不是真正存储的数据,也就是说变量存储的是一个指针,所以两个引用类型数据值可能一样,但是内存地址不一样。

let tmpA = ['body'];
let tmpB = ['body'];

const m = new Map();

m.set(tmpA, 'this is body');


m.has(tmpA); // true
m.get(tmpA); // 'this is body'

m.has(tmpB); // false
m.get(tmpB); // undefined

WeakMap结构

WeakMap结构和WeakSet结构非常非常相似,它们都是弱引用,并且它们的键只能是对象,不能是基本类型的值。当一个对象被WeakMap当作键/值,这次引用是不计入引用计数的,那么垃圾回收器回收的时候会回收掉这个对象,并且WeakMap会自动销毁这个键值对,如果在这个对象销毁后获取,将会返回undefined。

WeakMap只有四个方法。并且没有遍历方法,因为很有可能在遍历的过程中垃圾回收器就回收掉,所以没有遍历的方法。

WeakMap.prototype.set(key, value):设置一个键值对,并返回当前WeakMap对象。

WeakMap.prototype.get(key): 获取key键的值

WeakMap.prototype.has(key): 判断key键是否存在当前WeakMap结构中

WeakMap.prototype.delete(key): 删除当前WeakMap结构中的key键/值对。

WeakMap非常好用的是将WeakMap作为一些对象的状态值、属性值,当这个对象销毁的时候,那么WeakMap中的状态值就会跟着销毁,比如下面就是一个很好的例子,一个html网页,当发生click事件,就会在状态中+1,如果大于5次,就销将这个DOM节点;

const DOMclick = document.getElementById('site-navigation');
const wm = new WeakMap();

wm.set(DOMclick, {ClickNum: 0});

function clickFunction(...arg){
    let tmp = wm.get(DOMclick);
    if( tmp.ClickNum >= 5) {
        DOMclick.removeEventListener('click', clickFunction);
        DOMclick = null;
    } else {
        tmp.ClickNum += 1;
        wm.set(DOMclick, tmp);
        console.log('ClickNum: ',   wm.get(DOMclick).ClickNum);
    }

}

DOMclick.addEventListener('click', clickFunction);

文完

文档信息

发表评论

电子邮件地址不会被公开。 必填项已用*标注