ES6学习之Map WeakMap

带键(key)的集合

Map、WeakMap(映射) 和 Set(集合) 对象承载的数据元素可以按照插入时的顺序被迭代遍历。

Map

与Object的比较
Map的key值可以是任意类型(可以将原始值(字面量)存储为键),Object只能是字符串或Symbol。
Map可通过size获取数量(length=0),Object只能手动计算。
Map遍历遵循数据的插入顺序,Object自动排序。
Map可作为迭代器被迭代,Object需要其他方式(for in )迭代

使用

let map = new Map(); // 创建空的map
map.set(1, 'map中key为1的value'); // 添加或修改
console.log(map.get(1)); // 获取,返回value或undefined
console.log(map.has(1)); // 判断是否包含,返回Boolean
map.delete(1); // 删除

let obj = {
	name: '乔峰'
};
let map2 = new Map([[1, 'map2中key为1的value'], [2, obj]]); // 创建并初始化map,初始化格式[[key, value],[key, value]...]
console.log(map2.size); // 获取数量

let map3 = new Map(map2); // 浅拷贝
console.log(map3 == map2); // false
let map3_2 = map3.get(2);
map3_2.name = '虚竹';
console.log(obj); // {name:"虚竹"}
map3.clear(); // 清空

键的相等

// get的依据类似'===',虽然NaN!==NaN,但Map.get(NaN)可以被获取到
// 注意:+0 === -0
// Map可以设置键为NaN null undefined并获取
let map = new Map();
let obj = {};
map.set(NaN,1);
map.set({},2);
map.set(obj,3);
console.log(map.get(NaN)); // 1
console.log(NaN===NaN); // false
console.log(map.get({})); // undefined
console.log({}==={}); // false
console.log(map.get(obj)); // 3
console.log(obj===obj); // true

遍历

let map = new Map([
    [1, 'key为1的value'],
    [2, 'key为2的value'],
    [3, 'key为3的value']
]);
let entries = map.entries(); // 返回按插入顺序包含key/value映射的Iterator迭代器对象
let keys = map.keys(); // 返回按插入顺序包含key的Iterator迭代器对象
let values = map.values(); // 返回按插入顺序包含value的Iterator迭代器对象

// for of遍历
for (let [key,value] of map) {}
for (let [key,value] of entries) {}
for (let key of keys) {}
for (let value of values) {}

// forEach遍历(Iterator不能用forEach遍历)
map.forEach((value,key) => {});

与数组交互
创建和转化

let arr = [
    [1, 'key为1的value'],
    [2, 'key为2的value'],
    [3, 'key为3的value']
];
let map = new Map(arr); // Array转Map

let arr2 = Array.from(map); // Map转Array
let arr3 = [...map]; // 效果同arr2
console.log([...map]); // 展开运算符本质上是将Map对象转换成数组,打印同arr

// 补充说明:
// Array.from从一个类似数组或可迭代对象,创建一个新的浅拷贝的数组
let arrLike = {
    0: 'key为0的value',
    1: 'key为1的value',
    2: 'key为2的value',
    length: 3
}; // 类似数组对象
console.log(Array.from(arrLike)); // ['key为0的value', 'key为1的value', 'key为2的value']

合并:Map与Map或数组对象可以合并,但是会保持键的唯一性,同键被覆盖。

let first = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let second = new Map([
  [1, 'uno'],
  [2, 'dos']
]);

// 合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。
let merged = new Map([...first, ...second]);

// 合并Map和数组时,如果有重复的键值,则后面的会覆盖前面的。
let merged2 = new Map([...first, [3, 'ent']]);

console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
console.log(merged2.get(3)); // ent

规范
使用对象属性赋值方法可以给Map添加属性,但不会被Map的方法识别

let map = new Map();
map['age'] = 18;
console.log(map.get('age')); // undefined
map.delete('age'); // 并没有删除什么
console.log(map.age); // 18

WeakMap

与Map的区别
1.key必须是对象类型(Object),不能是基础数据类型
2.key键所引用(指向)的对象是弱引用。注意不是value值指向的对象。
3.Map是可迭代的(iterable),WeakMap是不可迭代的(key是弱引用)。

Map原理(个人理解)
Map会创建两个数组,一个存放键[…keys],一个存放值[…values],使用其API共用两个数组。
当从Map中取(get)某个值或修改(set)某个值时,Map会遍历所有的键[…keys],找到后利用索引再去获取值[…values]。这样有两个缺点:
1.赋值和搜索都需要遍历,消耗时间和内存。
2.[…keys]和[…values]会一直保留对key value的引用,这种引用使得垃圾回收算法不能回收处理他们,即使没有其他任何引用存在了。也就是会造成内存泄漏。

弱引用

解释1:在计算机程序设计中,弱引用与强引用相对,是指不能确保其引用的对象不会被垃圾回收器回收的引用。一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。

解释2:垃圾回收机制不考虑对该对象的引用。如果对象没有在其他地方被引用,则垃圾回收机制会回收该对象所占用的内存。

解释3:WeakMap可以把一个对象所关联的数据和该对象的生命周期联系起来。当对象被销毁,其关联的数据也被释放。

// 个人理解举例
let obj = {
    name:'乔峰'
};
let obj2 = {
    name:'虚竹'
};
let map = new Map();
map.set(obj, 1);
let weakMap = new WeakMap();
weakMap.set(obj2, 1);

obj = null; // 手动删除全局对{name:'乔峰'}的引用
obj2 = null; // 手动删除全局对{name:'虚竹'}的引用

setTimeout(()=>{
    console.log(map); // Map(1) {{…} => 1}
    console.log(weakMap); // WeakMap {}
}, 10000); // 设置时间长点,等待垃圾回收

使用

// 弱引用不能被枚举。所以WeakMap不能被遍历
let obj = {};
let weakMap = new WeakMap(); // 创建
weakMap.set(obj,1); // 添加/修改
console.log(weakMap.get(obj)); // 获取
console.log(weakMap.has(obj)); // 判断是否包含
weakMap.delete(obj); // 删除

// WeakMap的key是弱引用,所以WeakMap是不可被迭代的
// 下面代码报错:weakMap is not iterable
for(let [key, value] of weakMap) {}

// weakMap.clear()已被废弃,可重新创建一个空WeakMap替换来实现清空
weakMap = new WeakMap();

应用场景
1.给Dom添加数据或注册监听事件

let myImg = document.getElementById('myImg');
let weakMap = new WeakMap();
weakMap.set(myImg, {name:'',description:'',size:''});
// 或者
weakMap.set(myImg, function() {
	...handler
});
myImg.addEventListener('click', weakMap.get(myImg));

// 当myImg元素在页面中被注销(删除)后,weakMap绑定的数据或回调方法也会被垃圾回收机制处理

2.数据缓存
3.私有属性

参考

MDN:
Keyed collections
Map MDN
WeakMap MDN
其他:
ES6 系列之 WeakMap
WeakMap的应用场景

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值