owned this note
owned this note
Published
Linked with GitHub
# 展開與其餘參數
###### tags: `JavaScript`
展開運算子 / 其餘運算子 (spread operato / rest operator) 都是寫成 `...`,但使用上略有差異。
## 展開運算子 spread operator
### 類似 concat() 用法
以前要將 2 個陣列合併我們會用 `concat()`:
```javascript=
const ary1 = [1, 2];
const ary2 = [3, 4];
const newAry = ary1.concat(ary2); // [1,2,3,4]
```
透過使用展開運算子 `...` 我們除了縮短程式碼,也變得更容易閱讀:
```javascript=
const ary1 = [1, 2];
const ary2 = [...ary1, 3, 4]; // [1,2,3,4]
// 多個陣列合併
const newAry = [....ary1, ...ary2]; // [1,2,3,4]
```
<br>
### 將陣列展開傳入 function
在之前,如果想將陣列展開代入 function 參數的話,會用 `apply()`:
```javascript=
const ary = [1, 2];
function showNum(a, b){
console.log('a: '+a, 'b: '+b);
};
showNum.apply(null, ary); // "a: 1" "b: 2"
```
使用展開運算子就會變得方常方便並且好閱讀:
```javascript=
const ary = [1, 2];
function showNum(a, b){
console.log('a: '+a, 'b: '+b);
};
showNum(...ary); // "a: 1" "b: 2"
```
<br>
### 將可迭代 (literable) 的資料型別與類陣列(array-like)轉為陣列
在 JS 中可迭代 (literable) 的資料型別為:
- Array
- TypeArray
- String
- Map
- Set
- arguemtns
- DOM Elements
```javascript=
const str = 'Hello'
const strAry = [...str]; // ["H","e","l","l","o"]
// 將類陣列(array-like)轉為陣列
const els = document.querySelectorAll('p'); // 此為類陣列
els = [...els];
```
<br>
### 物件擴展
展開運算子也可以用於物件上,當我們想在某一個物件裡合併其他物件時:
```javascript=
const fnObj = {
sayHi() {
console.log('Hi');
},
};
const newFnObj = {
sayHello() {
console.log('Hello');
},
...fnObj // 將 fnObj 拷貝過來
};
/*
{
sayHello() {
console.log('Hello');
},
sayHi() {
console.log('Hi');
}
};
*/
```
<br>
### 淺拷貝(shallow copy)物件與陣列
接續上面所介紹的展開陣列與物件擴展,物件與陣列與物件因為傳參考(Call By Reference)的特性的關係,當我們把這 2 種資料賦予到其他的變數上時,修改其中一個陣列或物件裡的值,另一個也會隨之變動,展開運算子是一個個將值寫入,因此也可以拿來做淺拷貝。
```javascript=
const fnObj = {
sayHi() {
console.log('Hi');
},
};
const newFnObj = {
sayHello() {
console.log('Hello');
},
...fnObj // 將 fnObj 的內容淺拷貝過來
};
newFnObj.sayHi = 'Hi';
console.log(fnObj.sayHi); // ƒ sayHi() {console.log('Hi');}
console.log(newFnObj.sayHi); // 'Hi'
```
<br>
## 其餘運算子(其餘參數)rest operator
`...` 作為其餘運算子時又可以稱為**其餘參數**,作用如同其名,在宣告 funtion 時如果不確定會代入多少參數就可以使用其餘參數。
<br>
其餘參數有點類似 `arguments`,它也會回傳一個參數陣列,但它們有以下幾點不同:
- 其餘參數是真的陣列(可以使用陣列所有語法),而`arguments` 不是。
- 其餘參數可以自己決定從哪個位置的參數開始算起,而 `arguments` 會將所有傳入 function 的參數都傳入 `arguments` 的陣列裡。
- 其餘參數可以字定義變數名稱,而`arguments` 不能。
```javascript=
// 其餘參數寫法 ...變數名稱
function addUp(...num){
return num.reduce((acc, cur) => acc + cur, 0);
};
addUp(1, 2, 3, 4, 5); // 15
// 與其他參數混用
function updateTotal(curMoney, ...depositMoney){
return depositMoney.reduce((acc, cur) => acc + cur, curMoney);
};
updateTotal(500, 1100, 200, 50, -100); // 1750
```
在其餘參數出來後,現在 `arguments` 基本上都被其餘參數所取代。
<br>
###### 參考資料
- [鐵人賽:JavaScript 展開與其餘](https://wcc723.github.io/javascript/2017/12/24/javascript-spread-operator/)
- [[JavaScript] Javascript ES6 中的展開/其餘運算子(Spread operator/Rest operator)](https://medium.com/itsems-frontend/javascript-es6-spread-rest-operator-de8e0e020792)