# Array展開運算子spread operator、concat
###### tags:`JavaScript`
學習資源:[展開運算子(...) | MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
[codepen](https://codepen.io/yumyyang/pen/MWqaYrw)
## ES6陣列展開運算子
>MDN說明:展開運算子(...) 允許可迭代的陣列或字串展開成0到多個參數(如果是 function 的話)或是0到多個元素(如果是 array 或字組的話),或如果是物件的話則展開成0到多個 key-value pair。
1. **展開運算子的 ... 後面必定是接一個陣列或物件**
1. 把一個陣列展開為個別值`...array`也常用於Object
2. **不會更改到原陣列**
(若有第二層結構時,依據參考特性作處理)
### :triangular_flag_on_post:陣列常用
* 嵌入陣列
```javascript=
let dog1 = ['布丁狗','奇異狗']
let dog2 =['芒狗',...dog1,'蘋狗'] 
console.log(dog2)
//["芒狗","布丁狗","奇異狗","蘋狗"]
```
* 複製陣列
```javascript=
let dog1 = ['布丁狗','奇異狗']
let dog2 =[...dog1]
console.log(dog2)
//["布丁狗","奇異狗"]
```
* 合併多個陣列
```javascript=
let dog1 = ['布丁狗','奇異狗']
let dog2 =['芒狗','蘋狗']
dog2 = [...dog1,...dog2]
console.log(dog2)
//["布丁狗","奇異狗","芒狗","蘋狗"]
```
* 展開為各單一字元
```javascript=
let dog = [...'奇異狗'];
console.log(dog); // ["奇","異","狗"]
console.log(...dog); // "奇" "異" "狗"
console.log(...dog[0]); // "奇" 
let dog1 = ['布丁狗','奇異狗','奇異狗'];
console.log(...['布丁狗', '奇異狗']); // "布丁狗" "奇異狗"
console.log(...(['布丁狗', '奇異狗'][0])) // "布" "丁" "狗" //須注意先後順序為先抓第0筆再做展開
```
### :triangular_flag_on_post:用於Fn上
```javascript=
const numbers = [1,2,3];
function sum(a,b,c){
  return a + b + c;
}
const totalSum = sum(...numbers);
console.log(totalSum); //6
```
展開運算子將numbers的值展開給abc參數使用
### :triangular_flag_on_post:淺拷貝不改變原陣列的特性
```javascript=
let dog1 = ['布丁狗','奇異狗','芒狗'];
let dog2 = [...dog1]
dog2.push('增加一隻狗狗') //不會影響到dog1
console.log(dog1) //["布丁狗","奇異狗","芒狗"]
console.log(dog2) //["布丁狗","奇異狗","芒狗","增加一隻狗狗"]
```
**若在深層則會保留了原本的參考(references)**
```javascript=
let dog1 = ['布丁狗',['奇異狗'],'芒狗'];
let dog2 = [...dog1]
dog2[1],push('火龍狗')
cnosole.log(dog1) // ['布丁狗',['奇異狗','火龍狗'],'芒狗']
console.log(dog2) // ['布丁狗',['奇異狗','火龍狗'],'芒狗']
```
### :triangular_flag_on_post:用於Obj
* Obj的淺層與深層
```javascript=
const person = {
name: '小明',
obj: {}
}
//淺層不會連動更改 深層為傳參考因此會一同更改
const person2 = {...person};
//建立一個新的物件
person2.name = '小美';
//更改深層物件
person2.obj.name = 'person2的值'
console.log(person, person2)
```
* 合併物件
```javascript=
let obj1 = { name: 'foo', x: 10 };
let obj2 = { name: 'test', y: 20 };
// 複製物件
let clonedObj = { ...obj1 };
console.log(clonedObj);  // { name: 'foo', x: 10 }
// 合併串聯多個物件
// 與陣列不同的是: 有相同屬性名的,合併後只會使用最後一個物件的內容值
var mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj);  // { name: 'test', x: 10, y: 20 }
```
## concat()
[Array.prototype.concat() | MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)
>MDN:concat() 方法被用來合併兩個或多個陣列。此方法不會改變現有的陣列,回傳一個包含呼叫者陣列本身的值,作為代替的是回傳一個新陣列。
>
`Array.prototype.concat()`,在ES6後可以使用展開運算符將陣列合併讓程式變得更簡潔!
### :triangular_flag_on_post:合併陣列
```javascript=
let num1 = [1, 2, 3],
    num2 = [4, 5, 6],
    num3 = [7, 8, 9];
let nums = num1.concat(num2, num3);
console.log(nums)
```
### :triangular_flag_on_post:合併值到一個陣列
```javascript=
let alpha = ['a', 'b', 'c'];
let alphaNumeric = alpha.concat(1, [2, 3]);
console.log(alphaNumeric);
// ['a', 'b', 'c', 1, 2, 3]
```