# 四之 3、 JS 102 ES6
###### tags: `JS102` `JavaScript續` `2020八月第一週` `進度筆記` `Lidemy心得` 8/3
---
## 展開運算子 (spread operator)
一般單層陣列:
```
var arr = [1, 2, 3]
var arr2 = [4, 5, 6]
console.log(arr2)
```
會印出陣列 [4, 5, 6] 。
雙層 array :
```
var arr = [1, 2, 3]
var arr2 = [4, 5, 6, arr]
console.log(arr2)
```
會印出 [ 4, 5, 6, [ 1, 2, 3] ]
---
如果參了展開運算子:
```
var arr = [1, 2, 3]
var arr2 = [4, 5, 6, ...arr]
console.log(arr2)
```
則會印出 [ 4, 5, 6, 1, 2, 3 ] , 變成只有一層,可以把這個 array 內的值取出放到其他地方。
---
## spread operator 運用在 function 上
```
function add(a, b, c){
return a + b + c
}
var arr = [1, 2, 3]
console.log(add(arr))
```
這樣是印不出來的,因為 a 會是 1, 2, 3 , 而 b 和 c undefined 。
---
這時可以用 spread operator :
```
function add(a, b, c){
return a + b + c
}
var arr = [1, 2, 3]
console.log(add(...arr))
```
這樣會印出 6 , 因為把 array 展開了,就是把 `var arr = [ ]` 內的 1, 2, 3 取出放到 ...
----
## obj 也能用 spread operator
```
var obj1 = {
a: 1,
b: 2
}
var obj2 = {
z: 1
}
var obj3 = {
...obj1,
c: 3
}
console.log(obj3)
```
會印出 { a: 1, b: 2, c: 3 } , 會把原來 obj1 內的屬性 (記得 key/value) , 拿出來,直接貼到物件內,像是這個樣子:
```
var obj3 = {
a: 1,
b: 2,
c: 3
}
```
---
## 有優先順序
如果宣告 b: 3 , 會變成 ?
```
var obj1 = {
a: 1,
b: 2
}
var obj2 = {
z: 1
}
var obj3 = {
...obj1,
b: 3
}
console.log(obj3)
```
會印出 { a: 1, b: 3 } , 會直接改變 b 的值,在後面的會優先。
如果這樣寫 `b:2` 會蓋掉 `b: 3` :
```
var obj1 = {
a: 1,
b: 2
}
var obj2 = {
z: 1
}
var obj3 = {
b: 3,
...obj1
}
console.log(obj3)
```
後面的值會蓋掉前面的值,印出 { b: 2, a: 1 } 。
---
## 這樣寫的好處 ?
假設有一個 arr = [1, 2, 3] , 想讓 arr2 跟 arr 的值相同:
```
var arr = [1, 2, 3]
var arr2 = [1, 2, 3]
console.log(arr === arr2)
```
會是 false 兩個是不同陣列。
但用 spread operator 可以讓第二個 array 跟第一個 array 的值相同:
```
var arr = [1, 2, 3]
var arr2 = [...arr]
console.log(arr === arr2)
```
注意,這是 arr2 複製了 arr 的值,但仍是不同陣列 (type)。
---
## 底層記憶體運作
### array 的方面
假設今天我要將一個 nestedArray 插入到另外兩個 array 中:
```
var nestedArray = [4]
var arr = [1, 2, 3, nestedArray]
console.log('arr:', arr)
var arr2 = [...arr]
// 假如用了 spread operator , 運作如下面行;
// var arr2 = [1, 2, 3, nestedArray]
console.log('arr2:', arr2)
console.log(arr[3] === arr2[3])
```
會印出:
arr [ 1, 2, 3, [ 4 ] ]
arr2 [ 1, 2, 3, [ 4 ] ]
true
表示其 spread operator 從 arr 取出的值在 arr2 雖然類型不一樣,但都複製了相同的 nestedArray ,兩元素相等, 並指向同一個記憶體位置,去判斷會得到 true 。
---
### obj 的方面:
```
var obj = {
a: 1,
b: 2
}
var obj2 = {
...obj
}
console.log(obj, obj2, obj === obj2)
```
會印出 { a: 1, b: 2 } { a: 1, b: 2 } false , 雖然兩物件內值一樣,但是不同類型 (type) , 記憶體位置不同。
除非 `var obj = obj2` 。
---
參考資料:
[展開運算符與其餘運算符](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/rest_spread.html)
[[筆記] JavaScript ES6 中的展開運算子(spread operator)和其餘運算子(rest operator)](https://pjchender.blogspot.com/2017/01/es6-spread-operatorrest-operator.html)
---
# 四之 4、 JS 102 ES6 其餘參數 (rest parameters)
###### tags: `JS102` `JavaScript續` `2020八月第一週` `進度筆記` `Lidemy心得` 8/3
反向展開,[其餘參數 (rest parameter)](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/rest_parameters) 可以用於表示不確定數量的值(參數),並視為陣列。
---
## 反向展開
一般的展開運算子 (spread operator) :
```
var arr = [1, 2, 3]
var arr2 = [...arr, 4]
console.log(arr2)
```
會印出 [ 1, 2, 3, 4 ] 。
rest parameters 通常也會跟解構一起運用在 spread operator 就像是:
```
var arr = [1, 2, 3, 4]
var [first, ...rest] = arr
console.log(first)
console.log(first, ...rest)
console.log(...rest)
console.log(rest)
```
分別拿到
1
1 2 3 4
2 3 4
[ 2, 3, 4 ]
`...` 展開運算式拿出來的會是值,而純只有 rest parameter 可以直接拿陣列(物件)出來。
## rest parameter 只能放在最後面
rest element must be last element :
```
var arr = [1, 2, 3, 4]
var [first, ...rest, last] = arr
console.log(rest)
```
`...rest` 只能放在最後面,不能自動配對。
## 也可運用在 obj
```
var obj = {
a: 1,
b: 2,
c: 3
}
var {a, ...obj2} = obj
// var {a, ...rest} = obj;
// rest 可以更名成 obj2 或其他名字;
console.log(obj2)
```
因為 a 被拿開,剩下的參數是 b: 2 和 c: 3 , 所以只會印出 { b: 2, c: 3 } 。
## 可以展開後又集結回來
```
var obj = {
a: 1,
b: 2
}
var obj2 = {
...obj, // 展開 a:1, b:2 ;
c: 3
}
var {a, ...rest} = obj2
/*
因為用 , 把 a 拿開了
var {...rest} = obj2
console.log(rest)
*/
console.log(a, rest)
```
因為用 , 把 a 拿開了,所以會印出 1 { b: 2, c: 3 } , 只會對 `...` 接上的 rest 起作用,展開或收起來。
## 可以用在函式上
一般函式:
```
function add(a, b) {
return a + b
}
console.log(add(1, 2))
```
會印出 3。
運用 rest parameter :
```
function add(...args) {
console.log(args)
return args[0] + args[1]
}
console.log(add(1, 2))
```
印出:
[ 1, 2 ]
3
跟 [arguments](https://hackmd.io/@b9720012/HkM7vGXkD) 很像,但 arguments 是物件,但 ...args 是陣列。
```
function add(a,...args) {
console.log(args)
return a + args[0]
}
console.log(add(1, 2))
// console.log(add(1, 2, 3, 4, 5))
// 會得到更多陣列 [2, 3, 4, 5]
```
印出:
[ 2 ]
3
開頭會忽略掉 a 所以得到 [2] , 而 return a + args[0] 則會相加 1 和第 1 位的 2 ,所以得到 3 。
---
參考資料:
[展開運算子(Spread Operator)與其餘參數(Rest parameters)](http://oldblog.eddychang.me/blog/javascript/45-spread-operator-rest-parameters.html)
[Rest Parameters - 剩餘參數](https://jiepeng.me/2015/12/22/rest-parameters)
---
# 四之 5、 JS 102 ES6 預設參數 (default parameters) 就像是預設值
###### tags: `JS102` `JavaScript續` `2020八月第一週` `進度筆記` `Lidemy心得` 8/4
[預設參數 (default parameters)](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Default_parameters) 就像是預設值,沒有值進去或是值是未定義的情況,可以已預設值傳入。
---
假設有一個重複 n 次的字串:
```
function repeat(str, times) {
return str.repeat(times)
}
console.log(repeat('abc', 5))
```
會回傳 abc 並印出 abcabcabcabcabc 。
如果不傳 5 進去:
```
function repeat(str, times) {
return str.repeat(times)
}
console.log(repeat('abc'))
```
會印出 undefined , 但 ES6 的新功能,可以在函式內加入新值,例如:
```
function repeat(str, times = 5) {
console.log(times)
return str.repeat(times)
}
console.log(repeat('abc'))
```
就有會在函式內給 times 一個預設值 5 , 然後印出 abcabcabcabcabc 。
但如果最末行 repeat 甚麼都不要傳,然後開頭的函式 str 也給個預設值 Hello :
```
function repeat(str = 'Hello', times = 5) {
// console.log(times)
return str.repeat(times)
}
console.log(repeat())
```
就會印出 HelloHelloHelloHelloHello 。
## 也可以搭配解構使用預設值
```
function repeat(str = 'Hello', times = 5) {
// console.log(times)
return str.repeat(times)
}
const obj = {
a: 1, // 如果沒有 a: 1 就會印出 undefined ;
b: 2
}
const {a, b} = obj
console.log(a, b)
```
會印出 1 2 。
如果在物件內加上預設值:
```
function repeat(str = 'Hello', times = 5) {
// console.log(times)
return str.repeat(times)
}
const obj = {
// 如果沒有 a: 1 但最後幫他加入其他數字 ;
b: 2
}
const {a = 123, b} = obj
console.log(a, b)
```
就會印出 123 2 , 如果沒有 a: 1 但最後幫他加入其他數字的情況。
如果物件內有 a: 1 但是沒有 b 的情況:
```
function repeat(str = 'Hello', times = 5) {
// console.log(times)
return str.repeat(times)
}
const obj = {
// 如果沒有 a: 1 但最後幫他加入其他數字 ;
a: 1
}
const {a = 123, b = 'Hello'} = obj
console.log(a, b)
```
會印出 1 Hello 。
陣列也可以用,跟 array 很像,用途很多,加上預設值就可以少判段很多東西。
---
參考資料:
[Day 07: ES6篇 - Default Parameters(傳入參數預設值)](https://ithelp.ithome.com.tw/articles/10185343)