JS Map 与 weakMap

Map

Map 是 ES6 新增的一种集合类型,他是真正的键/值存储机制,在 ES6 之前通过对象存储“键值对”。

size 属性

每一个 Map 实例都有 size 属性,该属性表示该实例有多少对键值对。

const map1 = new Map([["key", "val"]]);
console.log(map1.size);// 1

基本API

  • 构建集 Map 合

使用 new 关键字创建一个 Map 实例,可以接收一个二维数组,作为初始化的数据。

const map1 = new Map();

const map2 = new Map([["key", "val"]]);
console.log(map2.size)//1

const map3 = new Map([[]]);
console.log(map3.has(undefined))//true
console.log(map3.get(undefined))//undefined
  • 新增键值对

创建实例后可以通过 set 方法添加键值对。第一个参数是 ,第二个参数是 。可以连续调用。

const map1 = new Map();
console.log(map1.size);//0

map1.set("key", "val");
console.log(map1.size);//1

map1.set("key1", "val1").set("key2", "key2");
console.log(map1.size);//3
  • 读取键对应的值

通过 get 方法获取 Map 实例的键对应的值。如果作为参数的键不在 Map 中则返回 undefined。接收一个参数即键。

const map1 = new Map();
map1.set("key", "val");
console.log(map1.get("key"))//val
console.log(map1.get("key1"))//undefined
  • 判断键值对是否存在

通过 has 方法判断该键是否存在 Map 实例中。存在返回 true,不存在返回 false。

const map1 = new Map([["key", "val"]]);
console.log(map1.has("key"))//true
console.log(map1.has("key1"))//false
  • 删除键值对

通过 delete 方法删除键值对。传入要删除的键。要删除的键在实例中则删除并返回 true,否则返回 false。

const map1 = new Map([["key", "val"]]);
console.log(map1.delete("key"))//true
console.log(map1.size);
console.log(map1.delete("key1"))//false
  • 清空 Map 集合

通过 clear 方法清空 Map 实例的键值对。

const map1 = new Map([["key", "val"]]);
console.log(map1.size);//1
map1.clear();
console.log(map1.size);//0
  • 对象作为键

Map 可以使用任意 JS 类型作为键,但是 Object 只能以数值、字符串、符号作为键。这意味着 Map 可以使用对象作为键。并且 Map 使用 SameValueZero(类似于严格对象相等)来确定键的匹配性。所以当对象作为键时,更改对象的属性并不会丢失映射关系

const obj = {}
const map1 = new Map([[obj, "val"]]);
console.log(map1.get(obj));//val
obj.name = "123";
console.log(map1.get(obj));//val

迭代

Map 能够按照键值对的插入顺序迭代输出。并且 Map 实例提供了一个迭代器以便能够通过特特定方法按顺序迭代。

  • entries

调用本方法会返回一个迭代器,并且是默认迭代器。所以可以使用扩展操作符,使用 for of 迭代 Map 实例时可以省略显示调用 entries();

const map1 = new Map([[1, 1], [2, 2]]);
for (let item of map1.entries()) {
  console.log(item);
}
console.log("-----------");
for (let item of map1) {
  console.log(item);
}
console.log("-----------");
console.log([...map1]);

在这里插入图片描述

  • keys

调用本方法会返回一个按照插入顺序的键的迭代器。

const map1 = new Map([[1, 1], [2, 2]]);
for (let item of map1.keys()) {
  console.log(item);
}

在这里插入图片描述

  • values

调用本方法会返回一个按照插入顺序的值的迭代器。

const map1 = new Map([[1, 1], [2, 2]]);
for (let item of map1.values()) {
  console.log(item);
}

在这里插入图片描述

  • 不使用迭代器
    当然也可以不使用迭代器而是用回调的方式迭代,示例如下。回调函数的第一个参数是值,第二个参数是键。
const map1 = new Map([[1, 1], [2, 2]]);
map1.forEach((val, key) => {
  console.log(key + ":" + val);
})

在这里插入图片描述
需要注意的是如果在迭代过程中修改给了每次迭代的结果,并不会影响映射关系,如下例

const map1 = new Map([[1, 1], [2, 2]]);
for (let item of map1.keys()) {
  item = 3;
  console.log(item);
}
console.log(map1.get(1));

在这里插入图片描述
由输出结果可知在遍历的过程中使 item 的值为 3,因此输出两次 3,最后通过原键仍然拿到了值。

Map 与 Object 最佳实践

大部分情况下使用 Object 和 Map 区别并不大,下面只是给出一些小小的建议。

  • 插入和删除性能:对于大多数浏览器引擎来说,当涉及到大量的插入和删除操作时,Map 的性能要优于 Object。
  • 查找速度:数据量非常大时,两者速度相差极小,如果涉及大量的查找操作,在一定条件下 Object 速度更快。
  • 内存:对于大多数浏览器来说,相同的内存,Map 大约可以比 Object 多存 50% 的键值对。

weakMap

weakMap 也是 ES6 新增的一种集合类型,它有如下特点:

  1. 键只能是 Object 类型或继承自 Object 类型,否则会抛出错误
  2. weakMap 实例对该键 Object 是弱引用(后边会详细讲),不会影响 JS 的垃圾回收
  3. weakMap 的基本 API 比 Map 的少了 clear(清空)方法,因为特点2,所以没有必要再持有该方法。
  4. weakMap 没有提供迭代其实例键值对的迭代器。因为特点2,所以 weakMap 实例中的键值对随时随地都有可能被销毁。
  5. weakMap 实例没有 size 属性
  6. weakMap 也可以像构建 Map 那样构建,也有 set、get、has、delete方法。

什么是弱引用

JS 有一种垃圾回收策略叫做引用计数,通俗理解就是声明一个对象后,JS 就会使用一个变量用来保存该对象被使用的次数,如果被使用次数为 0 ,那么 JS 就会销毁该对象,释放内存。

给个例子

const obj1 = { name: 1 }, obj2 = { name: 2 };
const map = new WeakMap([[obj1, 1], [obj2, 2]]);

这里弱引用的意思是当我实例化了一个 weakMap 集合 map,并且使用 obj1 和 obj2 作为键值对的键存入 map 中,那么此时 map 使用 obj1 和 obj2,但是由于 map 是 weakMap 实例,所以 obj1 和 obj2的被使用次数并不会加 1,那么一旦 obj1 和 obj2 又没有在别的地方被使用,JS 就会回收 obj1 和 obj2,map 就失去了键,自然获取不到值。

因此 weakMap 实例没有提供迭代器,因为也许你刚迭代完,该键就被回收了,内存都被释放了,那么此时的迭代就没有了意义。也正因此 weakMap 舍弃了 clear API。并且即使能够访问 weakMap 实例也无法看到其存储的键值对。

但是需要注意的是 weakMap 的值并不是弱引用,只要键存在,那么它对应的值一定不会被 JS 回收。

还需要注意 weakMap 的好兄弟 Map 就不是这样,Map 实例对于键的应用是强引用,只要 Map 实例没被回收,那么其存储键值对就会一直存在,不会被 JS 私自回收。

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值