将'arguments'传递给'apply()'是否安全?

时间:2013-05-14 12:51:55

标签: javascript

假设我有以下代码(完全没用,我知道)

function add( a, b, c, d ) {
  alert(a+b+c+d);
}

function proxy() {
    add.apply(window, arguments);
}

proxy(1,2,3,4);

基本上,我们知道apply需要一个数组作为第二个参数,但我们也知道arguments不是一个合适的数组。代码按预期工作,所以我可以安全地说我可以将任何类似数组的对象作为apply()中的第二个参数传递吗?

以下内容也适用(至少在Chrome中):

function proxy() {
  add.apply(window, {
    0: arguments[0],
    1: arguments[1],
    2: arguments[2],
    3: arguments[3],
    length: 4
  });
}

更新:似乎我的第二个代码块在IE< 9中失败了,而第一个(传递arguments)工作正常。 错误是Array or arguments object expected,因此我们将得出结论:传递arguments始终是安全的,而在oldIE中传递类似数组的对象是不安全的。

3 个答案:

答案 0 :(得分:7)

根据 MDN:

Function.prototype.apply的定义
  

fun.apply(thisArg[, argsArray])

     

您还可以使用arguments作为argsArray参数。 arguments是一个   函数的局部变量。它可以用于所有未指定的   被调用对象的参数。因此,你不必知道   使用apply方法时被调用对象的参数。您可以   使用arguments将所有参数传递给被调用对象。该   然后,被叫对象负责处理参数。

参考: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

第二个参数apply接受“一个类似于对象的数组,指定应该调用函数的参数”。据我所知,这个类似数组的对象应具有内部迭代的length属性,以及数字定义的属性(零索引)以访问值。

同样的情况也证实了我的规范http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.3,正如@Pointy所指出的那样。

答案 1 :(得分:3)

假设ECMAScript 5.1:是的。根据ECMA-262,10.6,arguments对象具有15.3.4.3(length)所需的Function.prototype.apply和索引属性。

答案 2 :(得分:1)

MDN只能代表Mozilla实施。所有实现都应遵守的实际spec说明如下:

15.3.4.3   Function.prototype.apply (thisArg, argArray)

When the apply method is called on an object func with arguments thisArg and
argArray, the following steps are taken:

1.  If IsCallable(func) is false, then throw a TypeError exception.
2.  If argArray is null or undefined, then
      Return the result of calling the [[Call]] internal method of func,
      providing thisArg as the this value and an empty list of arguments.
3.  If Type(argArray) is not Object, then throw a TypeError exception.
4.  Let len be the result of calling the [[Get]] internal method of argArray
      with argument "length".
5.  If len is null or undefined, then throw a TypeError exception.
6.  Let n be ToUint32(len).
7.  If n is not equal to ToNumber(len), then throw a TypeError exception.
8.  Let argList be an empty List.
9.  Let index be 0.
10. Repeat while index < n
      a. Let indexName be ToString(index).
      b. Let nextArg be the result of calling the [[Get]] internal method of
         argArray with indexName as the argument.
      c. Append nextArg as the last element of argList.
      d. Set index to index + 1.
11. Return the result of calling the [[Call]] internal method of func,
      providing thisArg as the this value and argList as the list of arguments.

The length property of the apply method is 2.

NOTE The thisArg value is passed without modification as the this value. This
     is a change from Edition 3, where an undefined or null thisArg is replaced
     with the global object and ToObject is applied to all other values and that
     result is passed as the this value.

似乎属性length和数字索引值是唯一的先决条件。