WeakSet 和 WeakMap

259 阅读2分钟

WeakSet 和 WeakMap都是为了解决内存泄漏的问题

WeakSet

相同点: 不重复值的集合

不同点:

  1. WeakSet 的成员只能是对象,不能是其他类型的值, WeakSet 里面的引用,都不计入垃圾回收机制, WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息
  2. 不可遍历
  3. 有三个方法: add, has, delete
  4. 没有size属性,没办法遍历他的成员
  5. WeakSet 的一个作用是存储DOM节点,不用担心这些节点从文档移除时候,会引发内存泄漏
ws.size // undefined
ws.forEach // undefined
ws.forEach(function(item){ console.log('WeakSet has ' + item)})
// TypeError: undefined is not a function

const foos = new WeakSet()
class Foo {
  constructor() {
    foos.add(this)
  }
  method () {
    if (!foos.has(this)) {
      throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
    }
  }
}

WeakMap

  1. WeakMap 跟Map相似,也是生成键值对的集合
  2. 区别1: 只接收对象作为键名,null除外
  3. 区别2: WeakMap的键名所指向的对象,不计入垃圾回收机制
  4. 如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap
  5. WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失
  6. 没有遍历操作,也就是 keys() ,values(), entries() 也没有size
  7. 只有四个方法,get set has delete
// WeakMap 可以使用 set 方法添加成员
const wm1 = new WeakMap();
const key = {foo: 1};
wm1.set(key, 2);
wm1.get(key) // 2
// WeakMap 也可以接受一个数组,
// 作为构造函数的参数
const k1 = [1, 2, 3];
const k2 = [4, 5, 6];
const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
wm2.get(k2) // "bar"
const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key

经典

const wm = new WeakMap();
const element = document.getElementById('example');
wm.set(element, 'some information');
wm.get(element) // "some information"

用途

let myWeakmap = new WeakMap();
myWeakmap.set(
  document.getElementById('logo'),
  {timesClicked: 0})
;
document.getElementById('logo').addEventListener('click', function() {
  let logoData = myWeakmap.get(document.getElementById('logo'));
  logoData.timesClicked++;
}, false);