浅析Map和WeakMap有什么不同之处、强/弱引用的区别、WeakMap详解、map的缺点和使用WeakMap的好处

一、Map 和 WeakMap 有什么不同之处

1、Map 是为了解决对象中的 key 只能为字符串的缺陷

//基本的对象
const obj = {
    'name': '张飞',,
    'age': 18
}
// Map
let m = new Map()
a.set(obj,1)

  我们的 Map 是可以解决对象的 key 不能为对象的缺陷,但是又随之而来了一个缺点:耗费内存,强引用

2、什么是 强 / 弱引用

  就是创建引用之后,无法被垃圾资源回收机制进行回收的,就是强引用。强到你设置了null,也分不开

const refence = [
    [obj: 1]
]

  现在我们把 obj 赋值为 null,但是我们的 [obj: 1] 是一个数组,也是一个引用的类型,把 obj 赋值为了空,但是 refence 和数组之前还是存在引用的关系,所以无法分开。

  因为我们都知道为了防止内存泄漏,通常把一个对象使用完之后设置为 null,那如果是上面这种情况,就算你设为 null 也无法垃圾回收了。

3、WeakMap 和 Map 的区别

  ES6 考虑到了这一点,推出了:WeakMap 。它对于值的引用都是不计入垃圾回收机制的,所以名字里面才会有一个"Weak",表示这是弱引用(对对象的弱引用是指当该对象应该被GC回收时不会阻止GC的回收行为)。

(1)强/弱引用的区别:Map 强,WeakMap 弱

(2)WeakMap 只接受对象为 key 值

  在实现完美的深拷贝中,我们使用 WeakMap 代替 Map 的使用来解决循环引用的问题,进行优化。

  Map 相对于 WeakMap :

(1)Map 的键可以是任意类型,WeakMap 只接受对象作为键(null除外),不接受其他类型的值作为键

(2)Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键;WeakMap 的键是弱引用,键所指向的对象可以被垃圾回收,此时键是无效的

(3)Map 可以被遍历, WeakMap 不能被遍历

  只要外部的引用消失,WeakMap 内部的引用,就会自动被垃圾回收清除。由此可见,有了它的帮助,解决内存泄漏就会简单很多。

二、WeakMap 详解

  MDN上说 WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。

  注意,WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。

  WeakMap 中,每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的key则变成无效的),所以,WeakMap 的 key 是不可枚举的。

  语法也很简单:const wp = new WeakMap();

  在使用的过程中我们需要注意 WeakMap 的 key 只能是 Object 类型

// 创建一个在每个实例中存储私有变量的对象
const internal = obj => {
  if (!wp.has(obj)) {
    wp.set(obj, {});
  }
  return wp.get(obj);
}

class Shape{
  constructor(width, height) {
    internal(this).width = width;
    internal(this).height = height;
  }
  get area() {
    return internal(this).width * internal(this).height;
  }
}

const square = new Shape(10, 10);
console.log(square.area);//100
console.log(map.get(square));//根据对象获得返回值 { height: 100,  100 }

  上面代码示例看到我们通过 internal(this) 然后去设置其属性。然后可以通过 map.get(square) 获取到 square 对象。

  WeakMap 好处是在遍历属性时或者在执行 JSON.stringify 时不会展示出实例的私有属性,但它依赖于一个放在类外面的可以访问和操作的 WeakMap 变量 ,WeakMap 每个键对自己所引用对象的引用是 "弱引用",这意味着如果没有其他引用和该键引用同一个对象,这个对象将会被当作垃圾回收,从而得到不确定的结果。

  就是说 WeakMap 里面的数据可能被垃圾回收机制清除或者一个对应在 WeakMap 结构的对象在外部被删除时,上述情况所对应的WeakMap的键值对也会被自动被移除。因此,如果你想要这种类型对象的 key 值的列表,你应该使用 Map。

  常用方法:

(1)WeakMap.prototype.delete(key):移除key的关联对象。执行后 WeakMap.prototype.has(key)返回false

(2)WeakMap.prototype.get(key):返回key关联对象,或者 undefined(没有key关联对象时)。

(3)WeakMap.prototype.has(key):根据是否有key关联对象返回一个Boolean值。

(4)WeakMap.prototype.set(key, value)在WeakMap中设置一组key关联对象,返回这个 WeakMap对象。

(5)WeakMap.prototype.clear() 从WeakMap中移除所有的 key/value 。  (参考 WeakMap)

  除了 WeakMap 还有 WeakSet 都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏。

  这里有一篇文章讲解的更详细,可以看看:《你不知道的 WeakMap》—— https://blog.csdn.net/z591102/article/details/106803124/

原文地址:https://www.cnblogs.com/goloving/p/15351803.html