解释 Addy Osmani 的粉碎杂志中的闭包内存泄漏示例
Explain Closure memory leak example in smashing magazine by Addy Osmani
我正在阅读 Smashing 杂志上的一篇博客,作者是 Addy Osmani 在闭包部分的内存高效 JS。我知道以下函数包含对 largeStr 的引用,而 GC 无法声明它。
var a = function () {
var largeStr = new Array(1000000).join('x');
return function () {
return largeStr;
};
}();
他在这里提到的解决方案没有引用 largeStr,GC 可以声明它。相反,他使用smallStr。
var a = function () {
var smallStr = 'x';
var largeStr = new Array(1000000).join('x');
return function (n) {
return smallStr;
};
}();
我明白了艾迪的观点,即不提及一件大事。但是,我想知道是否有任何(更好的)方法,我可以拥有第一个功能的功能并使其内存高效。
第一个函数创建largeStr
并返回引用它的函数。 因此,垃圾回收器无法释放largeStr
是合乎逻辑的,因为它仍在由现在包含在 a
变量中的函数使用。
第二个函数没有对largeStr
的持久引用,因此垃圾回收器可以释放它。
听起来你在问是否有办法保留对大东西的引用,但不使用该内存。 这个答案是否定的。
此外,这些在技术上根本不是"泄漏"。它们是合法的内存使用量。
通过不预生成大字符串,您可以在没有内存使用的情况下拥有第一个函数的功能。 如果您按需构建它,那么在有人调用该函数之前,它不会消耗任何内存。 这显然是执行速度和内存使用之间的直接权衡,但这是您在这里得到的选择。 如果它是预缓存的,那么它会消耗内存。 如果它仅按需构建,则在使用之前不会消耗内存。
以下是按需构建的版本,在使用之前不会消耗内存:
var a = function () {
return function () {
return new Array(1000000).join('x');
};
}();
不必写得这么晦涩。 也可以只是这样,因为不涉及闭包:
var a = function() {
return new Array(1000000).join('x');
}
这两个版本的缺点是每次调用a()
时都会创建字符串,但优点是不会永久缓存任何内容。 当a()
的所有用途都完成后,一切都会被垃圾回收。
或者,仅在首次使用时缓存它:
var a = function () {
var largeStr;
return function () {
if (!largeStr) {
largeStr = new Array(1000000).join('x');
}
return largeStr;
};
}();
这样做的好处是,在首次调用 a()
之前不会消耗内存,并且对 a()
的后续调用不必重新创建大字符串,但单个 largeStr 在创建后永远不会被垃圾回收。
哪个最好取决于您的使用模式,哪种权衡在您的设计/使用中更重要。
您需要非常刻意的设置才能导致 V8 闭包内存泄漏:
function create() {
var a = "x";
var b = new Array(1000000).join('x');
//Force context-allocation for b
(function(){b;});
return function() {
return a;
};
}
window.a = create();
代码无法访问b
,但在您完全摆脱window.a
之前无法收集它:
http://jsfiddle.net/bwPVe/
如果您在 chrome 中执行堆快照,您将看到。
- 在underscorejs模板中使用闭包
- Javascript闭包-如何防止内存泄漏
- 如何防止和防范闭包内存泄漏
- 在闭包中使用“self”会导致内存泄漏吗?
- 解释 Addy Osmani 的粉碎杂志中的闭包内存泄漏示例
- 试图理解Javascript闭包+内存泄漏
- 闭包编译器(ccjs)内存不足错误
- 闭包和内存泄漏
- 使用this/self-reference执行javascript闭包会导致内存泄漏
- node.js中可能导致内存泄漏的闭包示例
- js内存组织-闭包与对象
- javascript中的闭包和回调内存泄漏
- JavaScript中的闭包内存泄漏模式
- Javascript闭包:内存泄漏
- 如果dom元素有指向闭包的指针,如果从页面中删除dom元素会导致内存泄漏吗?
- 非循环引用的闭包内存泄漏
- 了解javascript闭包和内存使用情况
- 在闭包中使用全局对象会导致内存泄漏吗?
- Javascript闭包和内存问题
- 闭包内存泄漏并修复