19

将在 ECMAScript 6 中添加的 rest 参数的用途是什么?

例如,在 ECMAScript 5 中,您可以执行以下操作来获取从第二个元素开始的参数数组:

// ES 5
store('Joe', 'money');
store('Jane', 'letters', 'certificates');
function store(name) {
  var items = [].slice.call(arguments, 1); //['money'] in first case
  items.forEach(function (item) {
    vault.customer[name].push(item);
  });
}

这将等同于 ECMAScript 6 中的以下代码:

// ES 6
store('Joe', 'money');
store('Jane', 'letters', 'certificates');
function store(name, ...items) {
  items.forEach(function (item) {
    vault.customer[name].push(items)
  });
}

它们之间的区别仅仅是语法还是存在性能问题?

也适用于扩展运算符 (...)

//in ecmascript5
var max = Math.max.apply(null, [14, 3, 77]);
//but in ecmascript6
var max = Math.max(...[14, 3, 77]);

这只是语法更改还是性能问题?

4

6 回答 6

19

它们之间的区别仅仅是语法还是存在性能问题?

两者,还有更多...

休息参数:

  1. 是其他语言(Ruby、Python)中的已知习语
  2. 易于阅读和维护(与 相比slice)。
  3. 对于初学者来说更容易理解
  4. 可以(并且可能会)带来更好的性能,因为引擎可以优化。
  5. 工具更友好,因为它们可以静态分析。
于 2013-12-17T19:01:35.583 回答
18

除了@kangax 的回复,我会详细说明多次arguments调用对象时性能和正确性存在问题。如果您将arguments对象传递给另一个函数,则您将传递修改您范围内相应局部变量的权利。

function foo(arg) {
    bar(arguments);
    return arg;
}

function bar(args) {
    args[0] = 20;
}

foo(10) // 20

此功能的存在使函数内的局部推理无效,这使得 JIT 优化更加困难并引入了一定的安全隐患。为速度而设计的程序必须使用比惯用语更复杂的样板代码来解决这个问题,并且在安全上下文中,必须严格禁止Array.prototype.slice.call(arguments)传递。arguments

无需使用arguments对象来提取可变参数是新语法的众多优点之一。

于 2014-02-27T18:55:18.387 回答
4

在您给定的示例中,您直接传递对象文字。虽然仍然是语义的,但它似乎与扩展运算符的应用不相似。IMO,当列出每个参数时,展开运算符的价值会变得很明显,这会影响代码的可读性(以及可维护性,当替换传统的 push、splice、concat 方法时)。

使用扩展运算符

let nums = [1.25,5.44,7.15,4.22,6.18,3.11];   

function add(a, b, ...nums){
  let sum = parseInt(a + b);
  nums.forEach(function(num) {
    sum += num;
  })
  return parseInt(sum);
}

console.log(add(1, 2, ...nums)); //30

ES6Fiddle 演示(由traceur-compiler 编译

没有展开运算符

var nums = [1.25,5.44,7.15,4.22,6.18,3.11];   

function add(a, b, nums){
  var sum = parseInt(a + b);
  nums.forEach(function(num) {
    sum += num;
  })
  return parseInt(sum);
}

console.log(add(1, 2, nums)); //30

JSFiddle 演示

最后,我不认为使用扩展运算符会提高或阻碍性能,但是它确实提供了改进的代码可读性,并且可以说也是可维护性。遗憾的是,ES6 还没有被广泛实现,我会断言地推测浏览器支持需要一段时间才能实现。

有趣的事实:PHP 5.6 引入了类似的功能,其可变参数函数将变得func_get_args()多余。

于 2014-07-19T06:09:40.667 回答
4
于 2016-10-15T17:52:09.780 回答
3

我认为休息参数的主要区别是:

  • ECMA5 参数中的参数就像数组而不是数组,因此数组普通方法不可用,但在 ECMA6 参数中是一个数组。
  • 我认为在 ECMA5 代码示例中构建 items 数组会使代码变慢一些,因为新数组是实例化的。
于 2013-12-15T08:57:28.797 回答
1

休息运算符

function sumOfNumber(...args) {
    return args.reduce((a, b) => {
        return a + b
    })
}

console.log(sumOfNumber(1, 2, 3, 4))

扩展运算符

function sumOfNumber(args) {
    console.log(...args)
}

sumOfNumber([1, 2, 3, 4])
于 2020-03-14T19:45:39.273 回答