## 剩余参数 **剩余参数**允许我们将不确定数量的**剩余的元素**放到一个**数组**中。 比如说,当函数的实参个数大于形参个数时,我们可以将剩余的实参放到一个数组中。 **传统写法**: ES5 中,在定义方法时,参数要确定个数,如下:(程序会报错) ```javascript function fn(a, b, c) { console.log(a); console.log(b); console.log(c); console.log(d); } fn(1, 2, 3); ``` 上方代码中,因为方法的参数是三个,但使用时是用到了四个参数,所以会报错: ![](http://img.smyhvae.com/20180304_1638.png) **ES6 写法**: ES6 中,我们有了剩余参数,就不用担心报错的问题了。代码可以这样写: ```javascript const fn = (...args) => { //当不确定方法的参数时,可以使用剩余参数 console.log(args[0]); console.log(args[1]); console.log(args[2]); console.log(args[3]); }; fn(1, 2); fn(1, 2, 3); //方法的定义中了四个参数,但调用函数时只使用了三个参数,ES6 中并不会报错。 ``` 打印结果: ``` 1 2 undefined undefined 1 2 3 undefined ``` 上方代码中注意,args 参数之后,不能再加别的参数,否则编译报错。 下面这段代码,也是利用到了剩余参数: ```js function fn1(first, ...args) { console.log(first); // 10 console.log(args); // 数组:[20, 30] } fn1(10, 20, 30); ``` ### 剩余参数的举例:参数求和 代码举例: ```js const sum = (...args) => { let total = 0; args.forEach(item => total += item); // 注意 forEach里面的代码,写得 很精简 return total; }; console.log(sum(10, 20, 30)); ``` 打印结果:60 ### 剩余参数和解构赋值配合使用 代码举例: ```js const students = ['张三', '李四', '王五']; let [s1, ...s2] = students; console.log(s1); // '张三' console.log(s2); // ['李四', '王五'] ``` ## 扩展运算符(展开语法) 扩展运算符和剩余参数是相反的。 剩余参数是将剩余的元素放到一个数组中;而扩展运算符是将数组或者对象拆分成逗号分隔的参数序列。 代码举例: ```js const arr = [10, 20, 30]; ...arr // 10, 20, 30 注意,这一行是伪代码 console.log(...arr); // 10 20 30 console.log(10, 20, 30); // 10 20 30 ``` 上面的代码要仔细看: `arr`是一个数组,而`...arr`则表示`10, 20, 30`这样的序列。 我们把`...arr` 打印出来,发现打印结果竟然是 `10 20 30`,为啥逗号不见了呢?因为逗号被当作了 console.log 的参数分隔符。如果你不信,可以直接打印 `console.log(10, 20, 30)` 看看。 **举例**:数组赋值的问题 我们来分析一段代码:(将数组 arr1 赋值给 arr2) ```javascript let arr1 = ['www', 'smyhvae', 'com']; let arr2 = arr1; // 将 arr1 赋值给 arr2,其实是让 arr2 指向 arr1 的内存地址 console.log('arr1:' + arr1); console.log('arr2:' + arr2); console.log('---------------------'); arr2.push('你懂得'); //往arr2 里添加一部分内容 console.log('arr1:' + arr1); console.log('arr2:' + arr2); ``` 运行结果: ![](http://img.smyhvae.com/20180304_1950.png) 上方代码中,我们往往 arr2 里添加了`你懂的`,却发现,arr1 里也有这个内容。原因是:`let arr2 = arr1;`其实是让 arr2 指向 arr1 的地址。也就是说,二者指向的是同一个内存地址。 如果不想让 arr1 和 arr2 指向同一个内存地址,我们可以借助扩展运算符来做: ```javascript let arr1 = ['www', 'smyhvae', 'com']; let arr2 = [...arr1]; //arr2 会重新开辟内存地址 console.log('arr1:' + arr1); console.log('arr2:' + arr2); console.log('---------------------'); arr2.push('你懂得'); //往arr2 里添加一部分内容 console.log('arr1:' + arr1); console.log('arr2:' + arr2); ``` 运行结果: ![](http://img.smyhvae.com/20180304_1951.png) 我们明白了这个例子,就可以避免开发中的很多业务逻辑上的 bug。