【JS】函数参数arguments与rest参数解析

1,496 阅读3分钟

arguments对象

arguments对象是function(非箭头函数)中一个特殊的局部变量。 在ECMA262中对它是这么描述的:

其数组索引属性映射到其相关函数调用的形式参数绑定

我们可以看出它的内容,跟函数的形参有关,看下面的例子

function test(){
  console.log(arguments);
}
test(1,2);
test(1,2,3,4);

arguments

从arguments对象输出的内容我们可以看出

  • arguments内部的元素,跟函数实际传入参数的数值一致
  • 其index对应的数值,跟实际参数出传入的顺序也是一一对应的
  • 函数每次执行有自己的arguments对象

arrray实例

对比argumentsarray实例,我们可以看出来,首先它们相似的地方,就是都能够以这种index:value的实行保存值,但是他们的__proto__说明了他们不是同一个类型。

arguments的原型指向的是Object,而array的原型指向的是Array,所以arguments严格来说不是个数组,一般我们把它称作是伪数组或者类数组

arguments和array的异同点,我们可以简单总结为:

同:

  • 都有内置的length属性,保存值的方式都是index:value形式 异:
  • 原型不同,arguments原型是Object,因此不能调用Array原型上的各种操作方法
  • arguments有内置的Symbol(Symbol.iterator)属性

我们看到,arguments里面有Symbol(Symbol.iterator)属性,看到这个属性,如果我们了解Iterator的话,就知道,说明arguments是可以被for..of遍历的,所以,它可以被转换成一个数组对象。

arguments转为Array

Array.prototype.slice.call(arguments);
[].slice.call(arguments);

Array.prototype.slice方法不要求其this一定要是Array Object,只要当前this具有length属性以及形如index:value这种数据形式就可以转换为Array。

ECMA262-sec-array.prototype.slice

所以用callslice当前方法改为arguments,最后就可以返回一个由arguments转换而来的新数组。我们就可以对函数的参数进行操作了。

MDN-arguments JavaScript arguments 对象全面介绍

arguments的性能问题

For performance, it appears that accessing named arguments is also faster than accessing the arguments object in all the major browsers. In this jsperf performance test that just sums the first three arguments passed to a test function, using the named arguments was 2-8x faster than using the arguments object. The exact performance difference likely depends upon exactly what the function is attempting to do, but the arguments object definitely looks slower.

从性能角度而言:在所有主流浏览器中,访问命名参数比访问arguments对象速度要快得多。在js性能测试中总结了,在测试方法中使用命名参数访问效率要比使用arguments对象快到2-8倍。具体优化的速度可能取决于函数具体的实现,但是arguments对象的效率显然是偏低的。

Optimization killers

Is it a bad practice to access the arguments object to every function that takes parameters?

剩余参数(Rest Parameter)

function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

function(a, b, ...theArgs) {
  // ...theArgs保存的是剩余的实参
}

剩余参数与arguments的异同

  • 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
  • arguments对象不是一个真正的数组,而剩余参数是真正的Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach或pop。
  • arguments对象还有一些附加的属性 (如callee属性)。
  • 剩余参数必须放在最后

MDN-Rest_parameters