关注前端小讴,浏览更多原创技术文章
WeakMap
- WeakMap 是 ECMAScript6 的新增个性,是一种新的 汇合类型,是 Map 的“兄弟”类型,也是 Map 的子集
-
“weak”形容的是 JS 垃圾回收程序看待“弱映射”中键的形式
相干代码 →
根本 API
- 应用 new 关键字 和WeakMap 构造函数 能够创立一个空的弱映射
const wm = new WeakMap()
console.log(wm) // WeakMap {}
- 若映射的 键只能是 Object 或者 继承自 Object 的类型(非对象设置键会报错),值的类型无限度
// 应用嵌套数组初始化若映射
const key1 = {id: 1},
key2 = {id: 2},
key3 = {id: 3}
const wm1 = new WeakMap([[key1, 'val1'],
[key2, 'val2'],
[key3, 'val3'],
])
console.log(wm1.get(key1)) // 'val1'
console.log(wm1.get(key2)) // 'val2'
console.log(wm1.get(key3)) // 'val3'
// 只有有一个键有效就会抛出谬误,导致初始化失败
const wm2 = new WeakMap([[key1, 'val1'],
[key2, 'val2'],
[key3, 'val3'],
['key4', 'val4'], // TypeError: Invalid value used as weak map key
])
- 能够 将原始值包装成对象 再用作键
const key4 = new String('key4')
const wm3 = new WeakMap([[key1, 'val1'],
[key2, 'val2'],
[key3, 'val3'],
[key4, 'val4'],
])
console.log(wm3.get(key4)) // 'val4'
- 初始化后,能够应用
set()
增加键 / 值对,应用get()
和has()
进行查问,应用delete()
删除值(同 Map,但 WeakMap 没有 clear()办法,也没有自带的 size 属性)
const wm4 = new WeakMap()
console.log(wm4.size) // undefined,WeakMap 不自带 size 属性
const key5 = {id: 1},
key6 = {id: 2}
wm4.set(key5, 'Matt').set(key6, 'Frisbie')
console.log(wm4.has(key5)) // true
console.log(wm4.get(key5)) // 'Matt'
wm4.delete(key5) // 删除这个键值对
console.log(wm4.has(key5)) // false
console.log(wm4.get(key5)) // undefined
console.log(wm4.has(key6)) // true
// wm4.clear() // TypeError: wm4.clear is not a function,WeakMap 没有 clear 办法
set()
办法返回弱映射实例,因而能够把多个操作连缀起来,从初始化到增加键 / 值对(同 Map)
const wm5 = new WeakMap().set(key5, 'Matt')
console.log(wm5) // WeakMap {{ id: 1} => 'Matt' }
弱键
- 弱映射的 键不属于正式的援用,不会阻止垃圾回收
- 只有 键存在 , 键 / 值就存在 于映射中,并被当作对值的援用,不会被垃圾回收
const wm6 = new WeakMap()
wm6.set({}, 'val') // 初始化一个新对象作为建,没有指向这个对象的其余援用,代码执行后键和值均会被当作垃圾回收
const wm7 = new WeakMap()
const container = {key: {} } // container 对象保护着 wm7 中键的援用
wm7.set(container.key, 'val') // 键和值均不会成为垃圾回收的指标
container.key = null // 切断键对象的援用,键和值才会被垃圾回收
不可迭代键
- 弱映射中的键值对在 任何时候都能被销毁 ,因而 没有迭代键值对的办法
- 弱映射之所以 只能用对象作为键 是为了 保障只有通过键对象的援用能力获得值
应用弱映射
公有变量
- 公有变量会贮存在弱映射中,以 对象实例 为键 ,以 公有成员的字典 为值
- 用 闭包 把 WeakMap 包起来,让弱映射与外界齐全隔离开,实现闭包公有变量模式
–
const UserClosure = (() => {
// 用闭包把 WeakMap 包起来
const wm9 = new WeakMap()
class User {constructor(id) {this.idProperty = Symbol('id') // 创立符号
this.setId(id)
}
setId(id) {this.setPrivate(this.idProperty, id)
}
setPrivate(property, value) {const privateMembers = wm9.get(this) || {}
privateMembers[property] = value // {idProperty: Symbol(id): id }
wm9.set(this, privateMembers)
}
getId() {return this.getPrivate(this.idProperty)
}
getPrivate(property) {return wm9.get(this)[property] // 获取到 id
}
}
return User
})()
const user2 = new UserClosure(123)
console.log(user2) // User {idProperty: Symbol(id) }
console.log(user2.getId()) // 123
user.setId(456)
console.log(user.getId()) // 456
// console.log(wm9) // ReferenceError: wm9 is not defined,拿不到弱映射,无奈获取弱映射中对应的值,胜利设置公有变量
DOM 节点元数据
- WeakMap 实例不会障碍垃圾回收,因而非常适合 保留关联元数据
// 给节点关联元数据,保留在映射中
const m = new Map()
const loginButton = document.querySelector('#login')
m.set(loginButton, { disabled: true}) // 即便 DOM 被删除映射依然存在
// 给节点关联元数据,保留在弱映射中
const wm10 = new WeakMap()
const loginButtin2 = document.querySelector('#login')
wm10.set(loginButton, { disabled: true}) // DOM 被删除(若没有其余中央援用 loginButton)弱映射被回收
总结 & 问点
- WeakMap 属于什么类型?如何创立 WeakMap 类型?初始化后能够对其进行哪些操作?
- WeakMap 的键有什么限度?如果想应用原始值作为建,须要怎么的操作?
- WeakMap 的垃圾回收机制是什么?为什么说 WeakMap 适宜保留关联元数据?
- 写一段代码,用弱映射实现设置公有变量