最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • WeakMap and WeakSet (弱映射和弱集合)

    正文概述 掘金(coolFish)   2021-02-07   505

    我们知道,JavaScript 垃圾回收机制中,JavaScript 引擎在值可访问时将其存储在内存中。但是当引用消失时,该值就会被回收。

    // 该对象能被访问,coolFish 是它的引用
    let people = { name: "coolFish" };
    // 覆盖引用
    people = null;
    // 该对象将会被从内存中清除
    

    但是如果把一个对象放进数组中,那么只要数组在,对象就存在,即使没有对该对象的引用。

    let people = { name: "coolFish" };
    
    let array = [ people ];
    
    people = null; // 覆盖引用
    
    // 前面由 people 所引用的那个对象被存储在了 array 中
    // 所以它不会被垃圾回收机制回收
    

    如果我们使用对象作为常规 Map 的键,那么当 Map 存在时,该对象也将存在。它会占用内存,并且应该不会被(垃圾回收机制)回收。

    WeakMap

    WeakMap 和 Map 的第一个不同点就是 WeakMap 的键必须是对象,不能是原始值。

    let people = { name: "coolFish" };
    
    let weakMap = new WeakMap();
    
    weakMap.set(people, "ok"); // 正常工作(以对象作为键)
    
    weakMap.set("test", "Whoops"); // Error,因为 "test" 不是一个对象
    
    people = null; // 覆盖引用  // people 被从内存中删除了!
    

    我们可以发现,如果people 只是作为 WeakMap 的键而存在,他们会被从 map 中自动删除。 WeakMap 不支持迭代以及 keys()values() 和 entries() 方法。所以没有办法获取 WeakMap 的所有键或值。 我们可以用下面几个方法,获取一些我们想要的信息

    • weakMap.get(key) ,拿键取值。
    • weakMap.set(key,value) ,设置weakMap
    • weakMap.delete(key) ,根据键删除值
    • weakMap.has(key) ,是否包含该键

    这种限制的原因是,当 weakMap 中的对象失去他的所有引用,就会开始自动垃圾回收,垃圾回收时,可能会立即回收,也可能当前有很多回收任务,所以会延迟回收,这样我们就不知道**何时会被回收** ,因此不支持访问 WeakMap的所有键值的方法。

    WeakMap 使用场景

    WeakMap 的主要应用场景是 额外数据的存储。 例如我们在处理一个属于另外一个代码的一个对象,并且想存储一些相关的数据,那么这些数据就应该和这个对象共存亡,这时候 WeakMap 就是我们需要的,我们把这些数据放到 WeakMap 中,并且使用该对象作为这些数据的键 ,那么当该对象被垃圾回收了,数据也会被回收,同理,当数据不存在的时候,对象也会被回收。

    我们来看一个缓存案例

    //首先我们创建一个缓存函数
    let cache = new Map()
    //计算并且记住结果
    function process(obj) {
      if (!cache.has(obj)) {
        let result = obj;
        cache.set(obj, result);
      }
      return cache.get(obj);
    }
    
    //我们在其他文件使用他时
    let obj = {/* 假设我们有个对象 */};
    let result1 = process(obj); // 计算完成
    // ……稍后,来自代码的另外一个地方……
    let result2 = process(obj); // 取自缓存的被记忆的结果
    // ……稍后,我们不再需要这个对象时:
    obj = null;
    alert(cache.size); // 1(啊!该对象依然在 cache 中,并占据着内存!)
    

    小结:我们可以看到,我们应用缓存函数时,将我们传入的对象,作为 map 的键,所以当我们初始化对象的时候,该对象会依旧在 cache 中,因为他被定义在 cache 中的键。

    要解决该问题,我们可以使用 WeakMap 这样当键这个对象不可访问时,即便他作为键,他也会被一同被内存中删除。

    WeakSet

    • Set 类似,但是我们只能向 WeakSet 添加对象(而不能是原始值)。
    • 对象只有在其它某个(些)地方能被访问的时候,才能留在 set 中。
    • Set 一样,WeakSet 支持 addhasdelete 方法,但不支持 sizekeys(),并且不可迭代。

    我们可以把对象添加到 WeakSet中,以便去重,并且当对象不可读取时,他会进行垃圾回收。

    let visitedSet = new WeakSet();
    
    let john = { name: "John" };
    let pete = { name: "Pete" };
    let mary = { name: "Mary" };
    
    visitedSet.add(john); // John 访问了我们
    visitedSet.add(pete); // 然后是 Pete
    visitedSet.add(john); // John 再次访问
    
    // visitedSet 现在有两个用户了
    
    // 检查 John 是否来访过?
    alert(visitedSet.has(john)); // true
    
    // 检查 Mary 是否来访过?
    alert(visitedSet.has(mary)); // false
    
    john = null;
    
    // visitedSet 里将只有pete
    

    总结

    WeakMap 是类似于 Map 的集合,它仅允许对象作为键,并且一旦通过其他方式无法访问它们,便会将它们与其关联值一同删除。 WeakSet 是类似于 Set 的集合,它仅存储对象,并且一旦通过其他方式无法访问它们,便会将其删除。 它们都不支持引用所有键或其计数的方法和属性。仅允许单个操作。 WeakMapWeakSet 被用作“主要”对象存储之外的“辅助”数据结构。一旦将对象从主存储器中删除,如果该对象仅被用作 WeakMapWeakSet 的键,那么它将被自动清除。


    下载网 » WeakMap and WeakSet (弱映射和弱集合)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元