gpt4 book ai didi

javascript - 解释 Addy Osmani 的粉碎杂志中的闭包内存泄漏示例

转载 作者:行者123 更新时间:2023-12-02 18:50:31 24 4
gpt4 key购买 nike

我正在阅读 Addy Osmani 的精彩杂志 memory efficient 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在创建后永远不会被垃圾回收。

哪一个最好取决于您的使用模式以及在您的设计/使用中哪种权衡更重要。

关于javascript - 解释 Addy Osmani 的粉碎杂志中的闭包内存泄漏示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19505156/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com