Skip to content
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

关于WeakMap的一个问题 #362

Closed
vtxf opened this issue Mar 30, 2017 · 11 comments
Closed

关于WeakMap的一个问题 #362

vtxf opened this issue Mar 30, 2017 · 11 comments

Comments

@vtxf
Copy link

vtxf commented Mar 30, 2017

阮老师,你好!
打扰,问您一个问题。

Set 和 Map 数据结构一节讲到的 WeakMap 有这样一段代码:

var wm = new WeakMap();
var element = document.querySelector(".element");

wm.set(element, "Original");
wm.get(element) // "Original"

element.parentNode.removeChild(element);
element = null;
wm.get(element) // undefined

这个里面的这两句:

element = null;
wm.get(element) // undefined

是否可以理解为 wm.get(null),这样的话,貌似就和element没有关系了吧?
我是觉得wm.get(element)并没有办法来检测wm中是否存在没有赋值为null之前的element元素。不知是否有误?

我在chrome控制台上做了如下测试:
image
即使有另外一个变量alias引用了element,最后的结果也还是undefined。

@ruanyf
Copy link
Owner

ruanyf commented Mar 30, 2017

我举的这个例子不好。原意是销毁一个对象,导致它自动在wm之中消失,但是实际上造成了wm.get(null)的效果。

我一时想不出来其他销毁对象的例子,欢迎你帮忙一起想。

@ruanyf ruanyf closed this as completed Mar 30, 2017
@hax
Copy link

hax commented Apr 1, 2017

这个示例确实糟糕。。。

实际上 weakmap 就是允许你关联一个对象但不影响 gc 。可以写一个小对象关联一坨数据的例子,使用 weakmap 就允许小对象一旦被删,关联的一坨数据也会被释放掉(否则占用的内存无法回收)。

@zhliner
Copy link

zhliner commented Apr 3, 2017 via email

@hax
Copy link

hax commented Apr 6, 2017

在 node 里可以使用 process.memoryUsage() 来变相测试是否释放(需要占用足够大的内存以便观测)。

@vtxf
Copy link
Author

vtxf commented Apr 7, 2017

之前我一直用chrome的开发者工具测试,虽然那个里面有一个collect garbage的按钮,但是不管用。。
感谢hax提供的process.memoryUsage()这样的方法,我在node中做了如下测试来证明WeakMap的作用:
执行命令 node --expose-gc 后

> global.gc(); // 0 每次查询内存都先执行gc()再memoryUsage(),是为了确保垃圾回收,保证获取的内存使用状态准确
undefined
> process.memoryUsage(); // 1 初始状态,执行gc()和memoryUsage()以后,heapUsed为4M左右
{ rss: 21106688,
  heapTotal: 7376896,
  heapUsed: 4153936,
  external: 9059 }
> var wm = new WeakMap();
undefined
> var b = new Object();
undefined
> global.gc();
undefined
> process.memoryUsage(); // 2 创建WeakMap和对象b以后,heapUsed仍然为4M左右
{ rss: 20537344,
  heapTotal: 9474048,
  heapUsed: 3967272,
  external: 8993 }
> wm.set(b, new Array(5*1024*1024));
WeakMap {}
> global.gc();
undefined
> process.memoryUsage(); // 3 在WeakMap中加入元素b,值为一个5*1024*1024的数组后,heapUsed为45M左右
{ rss: 62652416,
  heapTotal: 51437568,
  heapUsed: 45911664,
  external: 8951 }
> b = null;
null
> global.gc();
undefined
> process.memoryUsage(); // 4 将b置为空以后,heapUsed变成了4M左右,说明WeakMap中的那个长度为5*1024*1024的数组被销毁了
20639744,
  heapTotal: 8425472,
  heapUsed: 3979792,
  external: 8956 }

@ruanyf
Copy link
Owner

ruanyf commented Apr 7, 2017

这个例子比我原先那个好多了,我要把它更新到书里。

太感谢大家了。:)

@foxdyor
Copy link

foxdyor commented Apr 26, 2017

阮老师,你好!发现在 http://es6.ruanyifeng.com/#docs/set-map 链接里的vtxf例子代码里有个笔误,const b = new Object(); 应为 var b = new Object(); 不然后边无法执行 b = null;谢谢

@ruanyf
Copy link
Owner

ruanyf commented Apr 26, 2017

@foxdyor 谢谢指出,已经改成let了。

@xgqfrms
Copy link

xgqfrms commented Jul 2, 2020

js manually GC

https://www.ruanyifeng.com/blog/2017/04/memory-leak.html

@SuperRun
Copy link

@ruanyf 阮老师,你好! 关于vtxf例子我有个疑惑,为什么GC之后,vm.get(b)还是能获取到数组 (我本来理解是对应的内存空间被销毁了那么相应地也获取不到数据了)
image

@shoyuf
Copy link

shoyuf commented Apr 24, 2021

@ruanyf 阮老师,你好! 关于vtxf例子我有个疑惑,为什么GC之后,vm.get(b)还是能获取到数组 (我本来理解是对应的内存空间被销毁了那么相应地也获取不到数据了)

你所展示的代码只进行了回收,没有进行清除引用

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants