zoukankan      html  css  js  c++  java
  • 浅析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/

  • 相关阅读:
    uni-app上拉加载
    uni-app 下拉刷新
    uni-app 的生命周期
    怎么看这个方法谁调用了?
    强推
    idea中spring热部署工具加载过慢问题彻底解决
    不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认设置的(overrideModeDefault="Deny"),或者是通过包含 overrideMode="Deny" 或旧有的 allowOverride="false" 的位置标记明确设置的。
    Springboot多数据源JdbcTemplate使用(非XA)
    关于Mysql报错:java.sql.SQLException: The statement (1) has no open cursor
    杂感记录
  • 原文地址:https://www.cnblogs.com/goloving/p/15351803.html
Copyright © 2011-2022 走看看