JavaScript WeakMap
WeakMap 对象
JavaScript 的 WeakMap 是一个键值对集合,其中 键 必须是对象。
WeakMap 保存对其键的 弱引用。
示例
// 创建一个 WeakMap
let myMap = new WeakMap();
// 创建一个对象
let myObj = {fname:"John", lname:"Doe"};
// 设置 WeakMap 的值
myMap.set(myObj, "player");
// 获取 WeakMap 的值let type = myMap.get(myObj);亲自试一试 »垃圾回收
JavaScript 使用一种称为垃圾回收的内存管理机制。
其主要功能包括:
- 确保高效利用内存资源
- 回收不再使用的变量占用的内存
- 防止内存泄漏
弱引用
与普通 Map 不同,WeakMap 并不会阻止其键被垃圾回收。
如果程序中没有任何对某个键(对象)的引用,它就会被垃圾回收。
当某个键被垃圾回收时,它的键值对会从 WeakMap 中移除。
示例
let myMap = new WeakMap();
let myObj = {fname:"John", lname:"Doe"};
myMap.set(myObj, "secret");
myObj = null;
// 现在 myMap 中的 myObj(及其值)可以被垃圾回收了键必须是对象
WeakMap 中不能使用原始值作为键。
键必须是对象或未注册的符号。
此限制与垃圾回收机制相关;原始值和对象的垃圾回收方式不同。
跟踪对象
WeakMap 中的条目是弱持有的:如果对象键变得不可达,则其映射会自动删除。
这非常适合跟踪对象数据,而不会妨碍垃圾回收。
追踪访客
let text = "";
// 创建一个 WeakMap 来存储访问次数
const visitsCount = new WeakMap();
// 创建访问者对象
const John = {name:"John", age:40};
const Paul = {name:"Paul", age:41};
const Ringo = {name:"Ringo", age:42};
const George = {name:"George", age:43};
// 跟踪访问量
track(Paul);
track(Ringo);
track(Paul);
track(Paul);
track(John);
// 用于跟踪访客的功能
function track(visitor) {
let count = visitsCount.get(visitor) || 0;
count++;
visitsCount.set(visitor, count);
text += visitor.name + ", age " + visitor.age + ", has visited " + count + " time(s).<br>";
}
亲自试一试 »自动清理
如果您移除对访问者对象的所有引用:
跟踪访问者:
John = null;
// John 的条目已从 WeakMap(人员)中移除。不可迭代
WeakMap 是不可枚举的。
您无法使用 for 循环、forEach() 或 keys() 遍历键和值。
您无法访问其大小。
有限方法
WeakMap 提供的方法集有限:
| new WeakMap() | 创建一个新的 WeakMap 对象 |
| get(key) | 获取 WeakMap 中指定键的值 |
| set(key, value) | 设置 WeakMap 中指定键的值 |
| delete(key) | 删除指定键的元素 |
| has(key) | 如果指定键存在于 WeakMap 中,则返回 true |
WeakMap 秘密数据
示例
// 创建 WeakMap
const myMap = new WeakMap();
// 私有字段模拟
class User {
constructor(name) {
myMap.set(this, {secret:"hidden data"});
this.name = name;
}
getSecret() {
return myMap.get(this).secret;
}
}
const user1 = new User("John");
secret = user1.getSecret();
亲自试一试 »示例详解
WeakMap 不允许迭代。
外部代码无法"发现"WeakMap 中存储的对象。
要获取密钥,需要构造函数中使用的 this 引用。
外部代码可以访问 user1 和 myMap,但无法访问 myMap 内部的 this 引用,除非显式地暴露它,例如通过 getSecret() 方法,否则密钥值是无法获取的。
隐私
WeakMap 的设计初衷就是为了保护隐私:你可以使用对象键来设置、获取、拥有和删除对象,但无法查看对象内部的内容。
在 JavaScript 语言引入 #private 字段之前,WeakMap 是模拟 JavaScript 类中私有属性的绝佳工具。
浏览器支持
WeakMap 是 ES6 特性。
自 2017 年 6 月起,所有现代浏览器均已完全支持 ES6。
| Chrome 51 |
Edge 15 |
Firefox 54 |
Safari 10 |
Opera 38 |
| 2016年5月 | 2017年4月 | 2017年6月 | 2016年9月 | 2016年6月 |
