我刚刚帮助一个新开发人员进行了一些面试,JavaScript是我的角色和我们正在招聘的角色的主要部分。老实说,应聘者并不是那么好,他并不真正理解JavaScript,然而在面试中,他混淆了JavaScript和C#,并开始讨论JS中的内存泄漏。我想要进行干预,但就在那时,我意识到我对JS中的内存泄漏知之甚少,除了它们占用了大量内存并减慢了速度。
当在采访中思考时,我唯一记得的是OReilly的Def Guide (我想这是第四版)提到了Mark和Sweep垃圾收集。但自从我读到这篇文章后,这一点一直在消失,我不能真的详细说明这一点。我在这个主题上很少找到清晰和简洁的东西(除了Crockford的一篇文章,它不是那么清楚)。
有人能尽可能简单地总结一下: JS中的内存泄漏是什么,我们如何发现它们,如何创建它们-我已经编写JS多年了,这完全打击了我的知识和信心,因为我从来没有真正考虑过它!
发布于 2012-01-17 23:27:33
实际上,在具有自动垃圾收集器的语言中,“真正的”内存泄漏是不可能的。因此,如果有一个内存泄漏,它总是底层引擎的错误(例如,在一些IE的named function expressions的问题)。
因此,在我们澄清了这一点之后,仍然可以使用javascript获得大量内存,并在不释放的情况下保留它。但这并不是真正的内存泄漏。例如,每个function call在ECMAscript中创建一个闭包。词法闭包的作用之一是复制对每个父上下文数据(激活和变量对象)的引用。因此,这需要一些内存,特别是在创建大量闭包的情况下。
另一个来自Javascript DOM世界的例子:我们使用new Image()创建一个动态图像,并将源设置为一个大图像。现在,我们有了对图像的引用,直到所有引用都消失或未使用(即使一个好的内存工具会正确地告诉你内存是用于图像而不是javascript),它才能得到垃圾回收。
但实际上,在这种语言中,只有这些场景才能真正“泄漏”内存。同样,这并不是真正的内存泄漏,就像您忘记再次free()该部分的C malloc()那样。因为在ECMAscript中没有动态内存管理,所以这个东西完全超出了您的范围。
发布于 2012-01-17 23:21:32
当谈到JS中的内存泄漏时,往往会提到闭包。示例如下:
http://www.javascriptkit.com/javatutors/closuresleak/index2.shtml
发布于 2012-01-17 23:33:44
var trolls = (function () {
var reallyBigObject = eatMemory();
// make closure (#1)
// store reallyBigObject in closure
(function () {
var lulz = reallyBigObject;
})();
// make another closure (#2)
return function () {
return 42;
};
})();您可能希望trolls仅为function () { return 42; },并且您可能希望reallyBigObject被移除并进行垃圾回收。
不是这样的,因为如果单个闭包(#1)引用了外部作用域中的变量。那么所有的闭包(#2也是)都会引用这个变量。
仅仅因为你引用了#2就意味着你引用了reallyBigObject,直到#2死了它才会被清除。
现在考虑一下您的平均闭包重架构,其中您将所有内容都包装在闭包中,并将它们嵌套在10个深度中。您可以看到保存对对象的引用是多么容易。
注意:以上详细信息适用于v8。任何完全兼容ES5的浏览器都会泄漏
var trolls = (function () {
var reallyBigObject = eatMemory();
return function () {};
})();因为根据ES5,每个内部函数都必须有一个对外部作用域中定义的每个闭包变量的引用。大多数浏览器都采用捷径,并以一种不明显的方式对其进行优化。
https://stackoverflow.com/questions/8897071
复制相似问题