ES6 新特性之 WeakMap 数据结构

概述

WeakMap结构与Map结构类似,也是用于生成键值对的集合

// 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"

WeakMap 与 Map 的区别有三点:

  • WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名
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
  • WeakMap 的键名所指向的对象,不计入垃圾回收机制

如果要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap,一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用 WeakMap 结构,当该 DOM 元素被清除,其所对应的 WeakMap 记录就会自动被移除

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

WeakMap 弱引用的只是键名,而不是键值,键值依然是正常引用

const wm = new WeakMap()
let key = {}
let obj = {foo: 1}

wm.set(key, obj)
obj = null
wm.get(key)
// Object {foo: 1}
  • WeakMap 没有遍历操作

WeakMap 的用途

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)

WeakMap 的另一个用处是部署私有属性

const _counter = new WeakMap()

class Countdown {
  constructor(counter) {
    _counter.set(this, counter)
  }
  dec() {
    let counter = _counter.get(this)
    if (counter < 1) return
    counter--
    _counter.set(this, counter)
  }
}

const c = new Countdown(2)
c.dec()

上面代码中,Countdown 类的内部属性 _counter 是实例的弱引用,所以如果删除实例,它也就随之消失,不会造成内存泄漏

本文转载自 http://es6.ruanyifeng.com/#docs/set-map#WeakMap 并进行整理

除特殊说明外本人博客均属原创,转载请注明出处:http://blog.johnhan.cn/blog_1042.html
鄂ICP备17018604号-1  鄂公网安备42060702000030号