# 四之 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)