在Javascript函数中使用新的ES2015 rest参数而不是使用数组参数有什么优点

What are the advantages of using the new ES2015 rest parameters in Javascript functions instead of using an array argument?

本文关键字:参数 数组 什么 rest 函数 Javascript ES2015      更新时间:2023-09-26

一些背景优先:http://www.ecma-international.org/ecma-262/6.0/

在ES2015中引入了许多新的javascript功能其中的rest参数,使函数能够接受不定数量的争论,同时避免一些不良做法比如使用函数的arguments属性。

在这些例子中,我们有两个做完全相同事情的js函数:

接受不定数量的参数

新方法:

(…args)=>Rest参数args被视为数组

function foo( ...bar){
  let ret = "";

  for(let i in args){
    ret += bar[i];
   
  }
  return ret;
}

此函数可以通过以下方式调用:

foo("a","b","c","d");   //returns => 'abcd'
let params = ["a","b","c","d"];
foo(...params);   //returns => 'abcd' 

旧方法:

function foo(bar){
  var ret, i;
  
  ret = "";
  bar = bar || [];
  for(i in bar){
    ret += bar[i];
   
  }
  return ret;
}

此函数可以通过以下方式调用:

var args = ["a","b","c","d"];
foo(args);   //returns => 'abcd' 

因此,这两种方法之间的唯一区别似乎只是调用函数的方式?

使用这个新功能还有其他优点吗?

rest参数的主要用例是,正如其名称所暗示的,不确定数量的"剩余"参数。

假设我们定义了一个ES5函数defer,它将Timeout设置为对任何参数的函数的调用:

function defer ( thisObject, callable ) {
   var args = Array.prototype.slice.call( arguments, 2 );
   setTimeout( function(){
      callable.apply( thisObject, args );
   }, 0 );
}
defer( window, alert, 'Merry...' )

使用rest参数,我们可以完全摆脱arguments,而无需更改函数签名:

function defer ( thisObject, callable, ... parameters ) {
   setTimeout( () => callable.apply( thisObject, parameters ), 0 );
}
defer( window, alert, "X'mas!" )

无需更改调用代码,而且我们的代码更干净。我们保留前两个参数,并自动将其余参数作为数组获取。这种模式并不罕见;CCD_ 3就是这样一个例子。

要点是在不强制调用方将所有内容都放入数组的情况下,去掉arguments。让一个函数只接受数组是很容易的,但该函数可能有数百个调用,所有这些调用都需要手动将参数包装到一个数组中,这甚至可能没有意义。

  1. 你喜欢defer( window, alert, ["Foo"] )还是defer( window, alert, "Bar" )

  2. defer( window, find, [] )还是defer( window, find )

  3. Array.of( [ foo, bar, bas ] )不是有点令人困惑吗?

  4. 就像Bergi所问的,为什么我们不把所有的参数都放在一个大的参数中呢?

希望这能澄清问题。不要忘记,功能不需要像箭头函数或模板字符串那样具有基础性即可发挥作用。

Rest参数允许展开可迭代对象并将其部分传递给函数。并非所有可迭代项都是数组;其他可迭代对象包括Strings、Maps和Sets。

当您编写一个接受数组参数的函数时,您只能向它传递一个数组:foo(arr)。但是,如果调用者没有数组,只有一个可迭代的,他们必须"arrayify"它:foo([...iterable])foo(Array.from(iterable))等。

当函数具有rest参数时,调用者可以传播任何可迭代的内容,例如字符串:foo(...'hello') === foo('h','e','l','l','o')。如果foo只接受一个数组,则无法执行此操作。

现在你可能会想,调用foo(...iterable)比调用foo([...iterable])容易多少?你是对的,这稍微容易一点,但不会太容易。rest参数只提供了一个更干净的语法,所以从技术上讲,我们可以重构所有函数,使其不使用它们。然而,正如这里的其他答案中所提到的,这会使我们的代码变得更加不可读。

console.log( ['value: ', value] )
Math.min( [69, 42, 420] )
setTimeout(func, 300, [])