---
# System prepended metadata

title: 展開運算符(Spread Operator)
tags: [JS]

---

<style> 
    body{font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft JhengHei', Roboto, 'Helvetica Neue', Arial, sans-serif;}
    .red-color{color:#f00}
    .blue-color{color:#f00}
</style>
###### tags: `JS`,
# 展開運算符(Spread Operator)
> [time=Mon, Dec 23, 2019 7:35 PM]
> [name=aikwdc00]
> 
## 概念
* 符號都是三個點(...)
* 都與陣列有關
* 展開陣列中的值


## 语法
```javascript=
//函数调用：
myFunction(...iterableObj);

// 字串
let str = 'kanboo'
console.log(...str);  // "k","a","n","b","o","o"

//陣列
let number = [1,2,3,4,5];
console.log(...number);  // 1,2,3,4,5

//字面量数组构造或字符串：
[...iterableObj, '4', ...'hello', 6];

//构造字面量对象时,进行克隆或者属性拷贝（ECMAScript 2018规范新增特性）：
let objClone = { ...obj };
```
淺層複製
另外陣列與物件相同都有著傳參考的特性，所以當把陣列賦予到另一個值上時，修改其中一個另一個也會跟著變動。

## 使用陣列特性
### 擴展了陣列本身，可以嵌入在陣列裡
```javascript==
let a1 = ['x', 'y'];
let a2 = ['w', ...a1, 'z'];

console.log(a2); // ['w', 'x', 'y', 'z']
```
### 複製陣列
```javascript==
let a1 = [1, 2];
let a2 = [...a1];

console.log(a2); // [1, 2]
```

#### set和...实现数组去重覆
* ES6 提供了新的数据结构 Set。它类似于数组，但是成员的值都是唯一的，没有重复的值。
```javascript=
const arr = [ 1,1,2,2,3,4,5,5,5 ]; 
const noRepeatArr = [ ...new Set(arr) ];
```
### 合併串聯多個陣列
```javascript==
let a1 = ['Hello', 'world'];
let a2 = [1, 2, 3];
a2 = [...a2, ...a1];

console.log(a2); // [1, 2, 3, 'Hello', 'world']

// 等同於
a2 = a2.concat(a1);
//----------------------------------------------------
var parts = ['shoulders', 'knees']; 
var lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]
```
### 使用在陣列的 push 方法上
```javascript==
let list = [1, 2];
list.push(...[3, 4]);

console.log(list); // [1, 2, 3, 4]

// 等同於
list.push.apply(list, [3, 4]);
```

### **類陣列轉成純陣列**
JavaScript 中有許多類陣列，這類陣列有著陣列的外皮，但卻不能使用陣列的方法，這類陣列由於原型不同，所以 不能 使用許多的陣列方法，如： map(), concat() 等等。

其中一種很常見的就是 **DOM 陣列**，此時我們就可以用 **展開運算子 轉為 純陣列**，這樣就可以使用陣列的各種方法。
```javascript=
// 可以將類陣列轉成陣列
let doms = document.querySelectorAll('p');
console.log(doms);
let spreadDom = [...doms];
console.log(spreadDom);
```
## 使用物件特性
```javascript==
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// { foo: "baz", x: 42, y: 13 }
```

```javascript==
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );

var mergedObj = merge ( obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }

var mergedObj = merge ( {}, obj1, obj2);
// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
```
## 參考資料
> [MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
> [IT幫幫忙-[ES6-重點紀錄] 擴展運算子 Spread Operator](https://ithelp.ithome.com.tw/articles/10195477)
> [ES6-展開運算子(Spread Operator)、其餘參數(Rest Operator)](https://kanboo.github.io/2018/01/26/ES6-SpreadOperator-RestOperator/)
> [從es6學js](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/rest_spread.html)
> [展開運算符與其餘運算符](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/rest_spread.html)