JesseZhao1990 / blog

learing summary
MIT License
62 stars 7 forks source link

WeakMap 的用途 #151

Open JesseZhao1990 opened 6 years ago

JesseZhao1990 commented 6 years ago

有时候我们想在某个对象上放一些数据,但是这会形成对这个对象的引用。当我们想释放这个对象所占用的内存。我们可能需要手动操作。稍不注意可能就会造成内存的泄露。WeakMap的设计的目的就是解决这个问题。WeakMap的键名所指向的对象,不计入垃圾回收机制。

使用场景举例

DOM相关的场景中

DOM 节点作为键名,当DOM节点被删除之后,即垃圾回收机制不考虑 WeakMap 对该对象的引用。DOM节点所占内存将会被释放。

拿阮一峰老师ES6那本书中的一个栗子吧.

let element = document.getElementById('idOfSomeDom');
let weakMap = new WeakMap();
weakMap.set(element,{timesClicked:0})

weakMap.addEventListener('click',function(){
      let eleData = weakMap.get(element);
      eleData.timesClicked++;
},false)

上面的代码中。element是一个dom节点,每当发生click事件,就把状态加1,我们将这个状态作为键值放在WeakMap里,对应的键名是element,一旦这个dom节点删除。该状态会自动消失。不存在内存泄露的风险。

Class的私有属性的部署

还是拿阮一峰老师书中的例子

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

class CountDown {
     constructor(counter, action){
         _counter.set(this, counter);
         _action.set(this, action);
     }
     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

在上面的例子中, CountDown类有两个内部属性_counter和_action, 是实例的弱引用,所以如果删除实例。他们也会随之消失,不会造成内存泄露。