假设我有这个函数,它(由于一些奇怪的原因)将其参数对象返回给调用者:
- function example(a,b/* ...*/) {
- var c = // some processing
- return arguments;
- }
存储调用的结果(var d = example();)是否会阻止示例(包含a,b,c等)的变量环境被垃圾收集? Arguments object的内部setter和getter可能仍然引用它,就像从闭包返回的函数一样.
我知道几乎没有用例(并且绕过Arguments对象被认为是不好的做法,很可能是因为它们与数组的相似性),但这更像是一个理论问题.不同的EcmaScript实现如何处理这个问题?
解决方法
考虑一下:
- var x = function() {
- return arguments;
- }
- console.log( x() === x() );
它是错误的,因为它不是相同的参数对象:它是(对于每个x的调用)一个新构造的对象,它具有存储在其中的所有参数的值.但它有参数的属性:
- 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; }
然而,还有更多.显然,如果返回参数,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属性指向与参数本身相同的数据集;再次,这是预期的.但是函数variable.callee.arguments之外的等于null(未定义).