【发布时间】:2012-11-11 01:04:51
【问题描述】:
假设我有这个草率模式函数,它(出于某种奇怪的原因)将其 arguments 对象返回给调用者:
function example(a, b/* ...*/) {
var c = // some processing
return arguments;
}
存储调用结果 (var d=example();) 是否会阻止对 example 的变量环境(包含 a、b、c 等)进行垃圾收集? Arguments object 的内部 setter 和 getter 可能仍然引用它,就像从闭包返回的函数一样。演示:
function example(a, b) {
var c = Array(1000).fill(0); // some large object
return {
args: arguments,
set: function(x) { a = x; },
get: function() { return a; }
};
}
var d = example('init');
console.log(d.get());
d.args[0] = 'arguments update'; // assigns the `a` variable
console.log(d.get());
d.set('variable update');
console.log(d.args); // reads the `a` variable
我知道几乎没有用例(传递 Arguments 对象被认为是不好的做法,很可能是因为它们与数组相似),但这更像是一个理论问题。不同的 EcmaScript 实现如何处理这个问题?它的实现是否接近规范?
我希望c 被垃圾回收like with a normal closure 并且不会被泄露,但是b 呢?如果我deletearguments 对象的属性会怎样?
【问题讨论】:
-
arguments的奇怪之处在于,命名参数实际上是伪数组元素的别名。试试吧!如果你改变arguments[0],那么a也会改变!我认为它不会因此而泄漏。 -
真的吗?我认为这是相反的情况:
arguments[0]是a的别名 :-) 规范中描述的算法表明arguments的索引是带有“ParameterMap”和指向调用的环境记录 - 泄漏恕我直言的可能原因。这就是为什么我还要询问实际的实现...... -
嗯,我想这是一个谜,它是它的别名 :-) 我在想的是,因为 arguments 对象基本上 是 参数集,它不需要对闭包或任何东西的引用,所以除了它直接使用的内存之外,它不会“固定”其他任何东西。然而,这只是一种预感,我不知道真实的故事。
-
FWIW,严格模式切断形式参数和参数对象之间的连接。改变一个不会改变另一个。换句话说,每个都获得自己传递参数的副本。
-
哦,元效应……这会在 7 年后重新开放吗?
标签: javascript memory-leaks arguments closures