Array.prototype.slice.call(arguments)和Array.apply(null,arguments)之间的区别

时间:2014-05-14 18:50:16

标签: javascript arrays

据我所知,这两个函数的行为方式相同:

function returnArgs() { return Array.prototype.slice.call(arguments) };

function returnArgs2() { return Array.apply(null, arguments) };

我看到这两种方法都在SO上引用,但仍然不能理解你为何使用其中一种方法。是偏好,还是有更实际的力量在起作用?也许我错过了一个明显的区别?

1 个答案:

答案 0 :(得分:4)

第二个非常危险,并且永远不会工作。尝试:

console.log(returnArgs2(3));

这将显示一个长度为3的空数组.Array构造函数将单个数字参数解释为您想要一个具有该长度的数组。

编辑 - 作为更新,基于some interesting information about optimization,如果有"危险"事情就在这里"泄漏" arguments个对象。根据那篇文章,将arguments从函数中传递出来会使函数代码的分析变得非常困难,因为arguments对象是如此奇怪。如果你想防止这种情况,安全的做法是:

function returnArgs() {
  var rv = [];
  for (var i = 0; i < arguments.length; ++i)
    rv.push(arguments[i]);
  return rv;
}

arguments.length的引用是可以的,对arguments对象的属性的引用也是如此,这些对象是与实际参数对应的整数。令人遗憾的是,更漂亮的&#34;这样做的功能性方法击败了优化器,但这并不奇怪。

&#34;怪异的&#34;关于arguments对象的事情是它为实际参数提供了别名。例如:

function foo(a, b) {
  arguments[1] = a;
  return b;
}

alert(foo("hello", "world")); // "hello"

arguments[1]的分配与对参数变量b的直接分配具有完全相同的效果,反之亦然。因此,如果arguments对象&#34;逃脱&#34;从函数中,静态分析代码不知道参数可能发生什么(基本上与局部变量相同),所以它只是放弃并留下要解释的函数。

请注意,优化程序文件是关于V8的,但代码分析的问题不依赖于运行时。 Nashorn是JDK 8中的新运行时,它有一种非常不同的优化方法,但我强烈怀疑滥用arguments的净效果是相似的。