Ber*_*rgi 8 javascript closures memory-leaks arguments
假设我有这个函数,它(由于一些奇怪的原因)将其arguments对象返回给调用者:
function example(a, b/* ...*/) {
var c = // some processing
return arguments;
}
Run Code Online (Sandbox Code Playgroud)
并存储一个调用的结果(var d=example();)防止的可变环境example(含有a,b,c等等)被当作垃圾收集?Arguments对象的内部setter和getter 可能仍然引用它,就像从闭包返回的函数一样.
我知道几乎没有用例(并且绕过Arguments对象被认为是不好的做法,很可能是因为它们与数组的相似性),但这更像是一个理论问题.不同的EcmaScript实现如何处理这个问题?
考虑一下:
var x = function() {
return arguments;
}
console.log( x() === x() );
Run Code Online (Sandbox Code Playgroud)
这是错误的,因为它不是同一个arguments对象:它(对于每次调用x)是一个新构造的对象,其中存储了所有参数的值。但它具有以下属性arguments:
var y = x([]);
console.log(y instanceof Object); // true
console.log(y instanceof Array); // false
console.log(y.length); // 1
console.log(y.callee + ''); // function() { return arguments; }
Run Code Online (Sandbox Code Playgroud)
然而,这还不止于此。arguments显然,如果返回,作为参数发送到函数的对象将不会被 GC 收集:
var z = x({some: 'value'});
console.log(z[0]); // {some:'value'}
Run Code Online (Sandbox Code Playgroud)
这是预期的:毕竟,您可以通过在函数内声明某个本地对象,将函数的第一个参数的值分配为其对象“0”属性,然后返回该对象来获得类似的结果。在这两种情况下,引用的对象仍将“使用中”,所以我想没什么大不了的。
但这又如何呢?
var globalArgs;
var returnArguments = function() {
var localArgs = arguments;
console.log('Local arguments: ');
console.log(localArgs.callee.arguments);
if (globalArgs) { // not the first run
console.log('Global arguments inside function: ');
console.log(globalArgs.callee.arguments);
}
return arguments;
}
globalArgs = returnArguments('foo');
console.log('Global arguments outside function #1: ');
console.log(globalArgs.callee.arguments);
globalArgs = returnArguments('bar');
console.log('Global arguments outside function #2: ');
console.log(globalArgs.callee.arguments);
Run Code Online (Sandbox Code Playgroud)
输出:
Local arguments: ["foo"]
Global arguments outside function #1: null
Local arguments: ["bar"]
Global arguments inside function: ["bar"]
Global arguments outside function #2: null
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,如果您返回arguments对象并将其分配给某个变量,则在函数内部它的callee.argument属性指向与其arguments自身相同的数据集;这又是预料之中的。但在函数外部variable.callee.arguments等于null(不是undefined)。
| 归档时间: |
|
| 查看次数: |
936 次 |
| 最近记录: |