如何在JavaScript中检测对象是否已被垃圾回收

2020-05-26 23:07:50

如果您正在用Javascript编写应用程序,很快您将不得不担心内存泄漏。但是,甚至很难知道是否存在内存泄漏。这个方便的方法可以有所帮助。起初,您可能认为WeakMap可以做到这一点。WeakMap/WeakSet将为您保留内容,但不要阻止对象被垃圾收集。一旦对象是GC';d,它就会从WeakMap或WeakSet中删除。因此,显而易见的解决方案是检查对象是否仍在WeakMap中。如果它丢失了,那么它就是GC';d。这不会起作用。问题是,WeakMap和WeakSet的设计目的是让你在不知道它在那里的情况下,无法获取里面的内容。要查找项目,您需要已经拥有该项目。这些集合甚至没有长度方法。要检查对象是否在WeakMap中,您必须已经有了对它的引用,因此可以防止它被垃圾收集。那么,它们有什么用呢?WeakMap最适合用于将对象链接在一起。例如,如果您有一组<;img>;元素,并且希望将某些数据与它们相关联,则只需执行img.myExtraproperty=";blah";即可。但是您的IDE可能会抱怨,因为HTMLImageElement没有这个属性。相反,您可以使用WeakMap。如果额外属性是单个值true,则使用WeakSet。一些浏览器,包括Chrome,但不包括Firefox,可以检查使用的Javascript内存量。因此,测试对象是否存在的解决方案是使其足够大,以便对内存产生明显影响。在下面的代码中,我使用WeakMap将一个1 GB的对象与您传入的任何内容关联起来。当释放对象并运行垃圾收集器时,预计还会释放至少1 GB的内存。这就是代码检查的内容。这个过程至少需要10秒,因为Chrome似乎每10秒才运行一次垃圾收集器。View on CodePen/**确定对象是否已释放@param obj是感兴趣的对象@param freFn是释放对象的函数。@返回解析为{freed:boolean,memory yDiff:number}@Author Steve Hanov&;[email protected]>;*/function isObjectFreed(obj,freFn){return new Promise((Resolean)=>;{if(!d,大型阵列也将是GCD,//其影响将是显而易见的。const allocSize=1024*1024*1024;const Wm=new WeakMap([[obj,new Uint8Array(AllocSize)]]);//等待内存计数器更新setTimeout(()=>;{const Beer=Performance.Memory y.usedJSHeapSize;//释放内存释放Fn();//等待GC运行,至少10秒setTimeout(()=>;},100);});}让foo={bar:1};isObjectFreed(foo,()=>;foo=null),然后((Result)=>;{Docent.write(`Object gcd:${result t.freed},${result t.ememyDiff}bytes freed`)},(Error)=>;{Docent.write(`Error:${error.message}`)})。

我使用此方法作为我的Zwibbler测试套件的一部分,Zwibbler是我的Javascript绘图应用程序。它有一个销毁()方法,该方法应该删除所有资源。但偶尔,我会有一些未删除的事件侦听器,它会保留对整个应用程序的引用。因此,当在诸如反应或角度之类的东西中使用它时,视图框架可以重复显示和隐藏它,因此完全释放资源是至关重要的。