Arguments对象是否泄漏?

时间:2012-11-22 15:36:33

标签: javascript memory-leaks arguments closures

假设我有这个函数,(由于一些奇怪的原因)将其arguments对象返回给调用者:

function example(a, b/* ...*/) {
    var c = // some processing
    return arguments;
}

存储调用结果(var d=example();)是否会阻止example(包含abc等)的变量环境垃圾回收? Arguments object的内部setter和getter可能仍然引用它,就像从闭包返回的函数一样。

我知道几乎没有用例(并且绕过Arguments对象被认为是不好的做法,很可能是因为它们与数组的相似性),但这更像是一个理论问题。不同的EcmaScript实现如何处理这个问题?

2 个答案:

答案 0 :(得分:3)

考虑一下:

var x = function() {
  return arguments;
}
console.log( x() === x() );

这是假的,因为它不是同一个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; }

然而还有更多。显然,如果返回arguments,GC将不会收集作为其参数发送的对象:

var z = x({some: 'value'});
console.log(z[0]); // {some:'value'}

这是预期的:毕竟,您可以通过在函数内声明一些本地对象,将函数的第一个参数的值指定为其对象'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);

输出:

Local arguments: ["foo"]
Global arguments outside function #1: null
Local arguments: ["bar"]
Global arguments inside function: ["bar"]
Global arguments outside function #2: null

如您所见,如果您返回arguments个对象并将其分配给某个变量,则在该函数内部,其callee.argument属性指向与arguments本身相同的数据集;再次,这是预期的。但是函数variable.callee.arguments之外等于 null (不是 undefined )。

答案 1 :(得分:0)

如果没有对特定的JavaScript引擎进行任何研究,很难确切地回答这个问题。然而,我认为arguments Objectexample创建的上下文之间的关系与任何其他局部变量及其主机上下文相同。

也就是说,存储该值也不需要存储其上下文。

一个警告是arguments.callee属性,它是对给定Function arguments所绑定的上下文(即Object)的引用。但是,此属性在严格模式下不存在,并且has been deprecated也不存在。

除此之外,我认为可以安全地假设返回和存储arguments Object不会导致内存泄漏。