-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES6 系列之 WeakMap #92
Comments
感谢,写的很清晰明了 |
感谢冴羽老师的分享 |
以前看阮一峰老师的ES6教程硬是没看懂,不知道是自己变强了还是老师写得太好了,茅塞顿开!嘿嘿 |
WeakMap 中四个方法好实现么 |
例子举的太好了! |
var t;
} let a=new Person('andy',18) t=a=null; 发现还是去除不了 |
emm,小白表示基础差看不大明白,知其然不知其所以然。希望不就之后再来会有茅厕顿开的感觉,先给老师32个赞 |
冴羽老师有一点我不太明白,阮一峰老师在ES6当中提到WeakSet以及WeakMap解决了 "引用计数" 这种垃圾回收机制存在的问题,但是在JavaScript高级程序设计一书当中表示现在的各大浏览器的垃圾回收机制已经全部使用的是 "标记清除" ,既然浏览器都已经替我们解决了这个问题,使用WeakSet和WeakMap还有什么作用吗?还请老师指点一二 |
是不可以简单理解,weakmap系统可以自动清除,map需要手动 |
应该这么翻译: |
经典没看懂 |
终于明白了弱引用,感谢 |
Node.js版本v14.15.1 process.memoryUsage(); // heapUsed: 3MB左右
const vm = new WeakMap();
let key = new Array(5 * 1024 * 1024);
process.memoryUsage(); // heapUsed: 44MB左右
vm.set(key, 1);
global.gc();
process.memoryUsage(); // heapUsed: 44MB左右
// 这里把key设置为null了之后,我在测了一下memory
key = null;
process.memoryUsage(); // heapUsed: 88MB左右
global.gc();
process.memoryUsage(); // heapUsed: 3MB左右 @mqyqingfeng 大佬,为啥我调用 |
我测了下是可以的,一些建议
|
|
前言
我们先从 WeakMap 的特性说起,然后聊聊 WeakMap 的一些应用场景。
特性
1. WeakMap 只接受对象作为键名
2. WeakMap 的键名所引用的对象是弱引用
这句话其实让我非常费解,我个人觉得这句话真正想表达的意思应该是:
翻译过来应该是 WeakMaps 保持了对键名所引用的对象的弱引用。
我们先聊聊弱引用:
在 JavaScript 中,一般我们创建一个对象,都是建立一个强引用:
只有当我们手动设置
obj = null
的时候,才有可能回收 obj 所引用的对象。而如果我们能创建一个弱引用的对象:
我们什么都不用做,只用静静的等待垃圾回收机制执行,obj 所引用的对象就会被回收。
我们再来看看这句:
正常情况下,我们举个例子:
使用这种方式,我们其实建立了 arr 对 key 所引用的对象(我们假设这个真正的对象叫 Obj)的强引用。
所以当你设置
key = null
时,只是去掉了 key 对 Obj 的强引用,并没有去除 arr 对 Obj 的强引用,所以 Obj 还是不会被回收掉。Map 类型也是类似:
我们可以通过 Node 来证明一下这个问题:
如果你想要让 Obj 被回收掉,你需要先
delete(key)
然后再key = null
:我们依然通过 Node 证明一下:
这个时候就要说到 WeakMap 了:
当我们设置
wm.set(key, 1)
时,其实建立了 wm 对 key 所引用的对象的弱引用,但因为let key = new Array(5 * 1024 * 1024)
建立了 key 对所引用对象的强引用,被引用的对象并不会被回收,但是当我们设置key = null
的时候,就只有 wm 对所引用对象的弱引用,下次垃圾回收机制执行的时候,该引用对象就会被回收掉。我们用 Node 证明一下:
所以 WeakMap 可以帮你省掉手动删除对象关联数据的步骤,所以当你不能或者不想控制关联数据的生命周期时就可以考虑使用 WeakMap。
总结这个弱引用的特性,就是 WeakMaps 保持了对键名所引用的对象的弱引用,即垃圾回收机制不将该引用考虑在内。只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。
也正是因为这样的特性,WeakMap 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakMap 不可遍历。
所以 WeakMap 不像 Map,一是没有遍历操作(即没有keys()、values()和entries()方法),也没有 size 属性,也不支持 clear 方法,所以 WeakMap只有四个方法可用:get()、set()、has()、delete()。
应用
1. 在 DOM 对象上保存相关数据
传统使用 jQuery 的时候,我们会通过$.data() 方法在 DOM 对象上储存相关信息(就比如在删除按钮元素上储存帖子的 ID 信息),jQuery 内部会使用一个对象管理 DOM 和对应的数据,当你将 DOM 元素删除,DOM 对象置为空的时候,相关联的数据并不会被删除,你必须手动执行 $ .removeData() 方法才能删除掉相关联的数据,WeakMap 就可以简化这一操作:
2. 数据缓存
从上一个例子,我们也可以看出,当我们需要关联对象和数据,比如在不修改原有对象的情况下储存某些属性或者根据对象储存一些计算的值等,而又不想管理这些数据的死活时非常适合考虑使用 WeakMap。数据缓存就是一个非常好的例子:
3. 私有属性
WeakMap 也可以被用于实现私有变量,不过在 ES6 中实现私有变量的方式有很多种,这只是其中一种:
ES6 系列
ES6 系列目录地址:https://github.com/mqyqingfeng/Blog
ES6 系列预计写二十篇左右,旨在加深 ES6 部分知识点的理解,重点讲解块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模拟实现、模块加载方案、异步处理等内容。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: