Javascript学习-WeakMap

一、含义

  WeakMap Map 一样,都是用于生成键值对的集合

const key=['1',2];
const myWeakMap=new WeakMap().set(key,'2');
console.log(myWeakMap.get(key))  // 2

 

  他也可以接受一个数组来作为参数:

const k1={key:'1'}
const k2={key:"2"}
const arr=[[k1,'1'],[k2,2]]
const myWeakMap=new WeakMap(arr)
console.log(myWeakMap.get(k1)) // 1

   

WeakMap 和 Map 的区别:

  (1)WeakMap 只接受对象(null 除外)作为键名

  (2)WeakMap 里面的键对象是不会被记入垃圾回收机制的。

注意:WeakMap 弱引用的只是键,而不是键值对,键值对还是正常引用的。

 

二、WeakMap 的语法

  WeakMap Map 在Api 上的区别主要是有两个,一个是没有遍历操作(没有key(),values()和entries()方法),也没有size 属性,因为没有方法列出所有的键名,某个键名是否存在是不可以被知道的,和垃圾回收机制是否运行相关。二是无法清空,即它不支持clear 方法。因此,WeakMap只有四个方法可以使用:get(),set(),has(),delete();

 

三、WeakMap 的用途

  (1)WeakMap 最常见的用途就是把DOM 节点作为键。如下:

let myElement =document.getElementById('logo');
let myWeakmap=new WeakMap();

myWeakmap.set(myElement,{timesClicked:0});

myElement.addEventListener('click',function(){
  let logoData=myWeakmap.get(myElement);
  logoData.timesClicked++
},false)

 

  上面的代码中,myElement 是一个 DOM 节点,每当发生了 click 事件就会更新一下状态,我们将这个状态作为键值放在了WeakMap 里面,对应的键名就是myElement,一旦这个Dom节点删除,这个状态就会消失,不存在内存泄漏的问题。
  
  进一步来讲,可以将事件处理程序存放到 WeakMap 里面来,如下:
const listener=new WeakMap()

listener.set(element1,handler1)
listener.set(element2,handler2)

element1.addEventListener('click',listener.get(element1),false)
element2.addEventListener('click',listener.get(element2),false)

   (2)WeakMap 的另一用途是缓存计算结果,如下:

const cache=new WeakMap() // 创建一个弱引用
function countKeys(obj){
  // 判断弱引用里面是否有obj
  if(cache.has(obj)){
    return [cache.get(obj),'cached']
  }else{
    const count=Object.keys(obj).length;
    cache.set(obj,count)
    return [count,'computed']
  }
}

let obj={name:'kakuqo',age:30};
console.log(countKeys(obj)) // [ 2, 'computed' ]
console.log(countKeys(obj)) // [ 2, 'cached' ]

obj=null;

  (3)WeakMap 还可以用来部署私有属性,如下:

const _counter=new WeakMap();
const _action=new WeakMap();

class Countdown{
  // 传递两个参数
  constructor(counter,action){
    _action.set(this,action);
    _counter.set(this,counter)
  }
  dec(){
    let counter=_counter.get(this);
    if(counter<1) return;
    counter--;
    _counter.set(this,counter);
    if(counter===0){
      _action.get(this)()
    }
  }
}

const c=new Countdown(2,()=>console.log('DONE'))
c.dec()
c.dec() // DONE

  由于传递的两个参数都是弱引用,如果删除这个实例,这两个参数也会随之消失,不会造成内存泄漏。

 

posted @ 2021-05-13 10:48  颗就完了  阅读(846)  评论(0编辑  收藏  举报