WeakMap 本身释放,而 keyObject 没有释放的情况下,value 会释放吗?
博客园markdown不太好看,可以转到git阅读https://sologgfun.github.io/look/
const keyObject = ['keyObject'];
new WeakMap().set(keyObject, ['value']);
问题:现在 ['value'] 会被释放吗?
听说WeakMap是o(1)复杂度的,而且不会存在内存泄漏问题,那么就只有一种实现机制,就是value直接通过一个隐形键挂在keyObject上。
但如果是这样,而WeakMap本身又没有引用它之前添加过那些内容,那么是不是如果keyObject不释放,即便WeakMap实例释放了,通过该WeakMap实例添加在keyObject上的value是不是也都不会释放,从而形成另一种内存泄漏?
jsperf.com只能测试性能,不知道内存泄漏该如何测试?
答案:会正确被释放
测试过程:
[1]Chrome DevTools 控制台上有一个小众的 API 叫
queryObjects()
,它可以从原型树上反查所有直接或间接的继承了某个对象的其它对象,比如
queryObjects(Array.prototype)
可以拿到所有的数组对象,
queryObjects(Object.prototype)
则基本上可以拿到页面里的所有对象了(除了继承自Object.create(null)的对象之外)。而且关键是这个 API 会在内存里搜索对象前先进行一次垃圾回收。
【测试1】
const key = new WeakMap();
const map = new WeakMap();
map.set(key, new WeakMap());
undefined;
在chrome控制台运行
查到了 3 个对象,符合预期
【测试2】
const key = new WeakMap();
new WeakMap().set(key, new WeakMap());
undefined;
在chrome控制台运行
只有一个WeakMap没有被回收
那么WeakMap是怎么做到的呢?
核心在于WeakMap上的kv对是弱引用的
V8 的实现,是在 GC 上开洞的
https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/objects/hash-table.h#L336
里用的就是这个 EphemeronHashTable,EphemeronHashTable 存储着的键和值都是弱引用
let wm = new WeakMap([[k1, v1], [k2, v2]]) // vm = {k1:v1, k2:v2}
wm.size // no such property
wm.keys(); // no such function
wm.forEach(...) // unable to be iterated
WeakMap有2个特点
- 属性不可枚举
- key必须是Object类型
看一下WeakMap的polyfill
var WeakMap = function() {
this.name = '__wm__' + uuid()
};
WeakMap.prototype = {
set: function(key, value) {
Object.defineProperty(key, this.name, {
value: [key, value],
});
return this;
},
get: function(key) {
var entry = key[this.name];
return entry && (entry[0] === key ? entry[1] : undefined);
},
...
};
- weakmap.set(key, val)事实上是直接通过Object.defineProperty给这个key加了一个新属性
—— WeakMap的key必须是Object类型的原因
- 相比Map,WeakMap持有的只是每个键值对的“弱引用”,不会额外开内存保存键值引用。这意味着在没有其他引用存在时,垃圾回收器能正确处理key指向的内存块。
—— WeakMap的key不可枚举的原因
延伸阅读
1.Object.defineProperty(obj, "prop", propDesc)和obj.prop = value的区别?
2.什么是弱引用?
垃圾回收机制不考虑对该对象的引用。
也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象是否还在该弱引用的结构中。
WeakMap不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。
参考资料
- https://www.zhihu.com/question/344771857
- https://www.jianshu.com/p/8c4ffa77b346
- http://es6.ruanyifeng.com/#docs/set-map#WeakSet
最新文章
- DevExtreme官方视频教程分享
- SSRS报表参数设置
- 解决多网卡SNMP获取不到数据的问题
- August 5th, 2016, Week 32nd, Friday
- 用UltralSO安装CentOS 和 Ubuntu
- Android中Context详解 ---- 你所不知道的Context
- UserLogin
- 使用C语言获取当前系统的时间
- 小tip:我是如何初体验uglifyjs压缩JS的
- android ListView用法介绍
- cygwin在Windows8.1中设置ssh的问题解决
- 使用ANR-WatchDog来检測ANR
- VS2012下基于Glut OpenGL glEdgeFlag示例程序:
- LightOJ 1234 Harmonic Number 调和级数部分和
- devexpress显示缓冲滚动条与实现类似QQ消息推送效果
- java多线程之内存可见性-synchronized、volatile
- JS继承以及继承的几种实现方式总结
- Jmeter上传附件EXCEL
- Python网络编程之Socket的简单实现
- Django-Oscar小记:如何使用高版本Django开发网页的SEO模块
热门文章
- 拼写单词[哈希表]----leetcode周赛150_1001
- EOS源码分析:transaction的一生
- Springboot整合html 报java.lang.IllegalArgumentException: Root element name cannot be null
- spring security中@PreAuthorize注解的使用
- LSTM 反向传播算法
- 【入门】广电行业DNS、DHCP解决方案详解(一)——历史及现状篇
- js获取Cookie,获取url参数
- NLP(十九) 双向LSTM情感分类模型
- vmware12中安装MAC OS X 10.10
- POJ-3169 Layout (差分约束+SPFA)