--- title: 'JavaScript ES6 筆記' disqus: Pai --- # 壹、目錄及代辦事項 ## Table of Contents [TOC] ## 待學習項目 - [ ] - - [ ] - - [ ] - - [ ] - # 貳、使用 let 與 const 宣告變數 ### 1. 使用 var 與 let 的不同 - 因為 Hoisting(提升) 的關係,這個結果第一個 console.log 會出現 undefined。 - 記憶題已經為 mom 這個變數準備了記憶體的位置 ```javascript= console.log(mom); var mom = '老媽'; (function () { console.log(mom); })(); //undefined //老媽 ``` - 這個結果則會出現 Uncaught ReferenceError ,告訴你你還沒宣告這個變數。 ```javascript= console.log(mom); let mom = '老媽'; (function () { console.log(mom); })(); ``` ### 2. 使用 var 與 let 作用域的差異 var 的作用域是 function scope: var 的作用域會在整個 funciton 裡面 let 的作用域是 block: 指 let 的作用域就指在它存在的 {} 內 #### a. 使用 var 的時候,因為作用域在整個 function 內,所以在 if(true) 裡面宣告,ming 的結果會改變。 ```javascript= function varMing () { var ming = '小明'; if (true) { var ming = '杰哥'; } console.log(ming); } varMing ()// '杰哥' ``` #### b. 使用 var 的時候,因為作用域只限制在 let 所在的 {} 裡面,不會改變到外層的變數。 - 範例一 ```javascript= function varMing () { let ming = '小明'; if (true) { let ming = '杰哥'; } console.log(ming); } varMing ()// '小明' ``` - 範例二 - 因為 i 的作用域在整個 function{} 內,console 和 setTimeout 是同時執行的,console 馬上就執行完畢了,但 setTimeout 要等三秒,三秒過後,i 得到的值就是最後全域變數裡的 10 了。 - 而 i 不是只到 9 嗎? 為什麼最後的結果會呈現 10,這是因為 i 吃到全域變數的值,而 i 在執行第 10 次時,因為條件不符合,就沒有繼續執行{}內的內容,不過在 window i 就紀錄為 10 了。 ```javascript= for (var i = 0; i < 10; i++) { console.log(i); setTimeout(function () { console.log('這執行第' + i + '次'); }, 3000); } // 1,2,3,4,5,6,7,8,9 //這執行第 10 次 ``` - - 當把 var i = 0 改成 let i = 0,最主要影響 setTimeout中輸出 i 的值,原因是使用 let 宣告變數的話,會有區塊作用域的特性,因此每一次迭代都會重新綁定,所以 setTimeout 在時間倒數結束後,區塊作用域會是當時候的變數 i 值. ```javascript= for (let i = 0; i < 10; i++) { console.log(i); setTimeout(function () { console.log('這執行第' + i + '次'); }, 3000); } // 1,2,3,4,5,6,7,8,9 //這執行第1次 //這執行第2次 //這執行第3次 //這執行第4次 //這執行第5次 //這執行第6次 //這執行第7次 //這執行第8次 //這執行第9次 ``` #### b. 如何在 var 的情況下做出與用 let 宣告的效果 ```javascript= for (var i = 0; i < 10; i++) { console.log(i); setTimeout(function () { console.log('這執行第' + i + '次'); }, 3000); } // 1,2,3,4,5,6,7,8,9 //這執行第 10 次 ``` 使用立即函式 ```javascript= for (var i = 0; i < 10; i++) { console.log(i); (function(i){setTimeout(function () { console.log('這執行第' + i + '次'); }, 3000)})(i); } ``` ### 3. const 常數 #### a. const 宣告後值就不能被修改 ```javascript= const ming = '鐵錚錚男子漢'; ming= '騙人'; //這樣就會出現錯誤 ``` #### b.但是用 const 宣告的物件是可以修改的 因為物件是傳參考,只要沒有把參考值替換掉,就可以修改 ```javascript= const family = { mom: '老媽', me: '小明', sister: '小橙' }; family.mom = '爸爸'; //{mom: "爸爸", me: "小明", sister: "小橙"} ``` # 参、展開與其餘參數 ### 1. 使用展開語法,合併陣列 - ES5 的語法 ```javascript= let groupA = ['小明', '杰倫', '阿姨']; let groupB = ['老媽', '老爸']; let groupAll = groupA.concat(groupB); console.log(groupAll);// ["小明", "杰倫", "阿姨", "老媽", "老爸"] ``` - 使用 ES6 展開語法 - ...就是把陣列裡面的值一個一個取出來,例如:小明 杰倫 阿姨 ```javascript= let groupA = ['小明', '杰倫', '阿姨']; let groupB = ['老媽', '老爸']; let groupAll = [...groupA,...groupB]; console.log(groupAll);// ["小明", "杰倫", "阿姨", "老媽", "老爸"] console.log(...groupA); //小明 杰倫 阿姨 ``` ### 2. 淺複製觀念說明 (shallow copy) 陣列和物件都有傳參考的特性,運用...可以淺複製出另一個陣列,就可以獨立於原陣列產生一個新陣列。 ```javascript= let groupA = ['小明', '杰倫', '阿姨']; let groupB = [...groupA]; groupB.push('阿明'); console.log(groupA); //["小明", "杰倫", "阿姨"] console.log(groupB); //["小明", "杰倫", "阿姨", "阿明"] ``` ### 3. 類陣列的觀念講解 - 當傳入的值 updateEasyCard(),沒有給變數時,傳入的值都會被放在 arguments 裡面 - 這邊的 arguments 為類陣列,並非真正的陣列。 - 但要使用 reduce,前面的 arg 必須是陣列,因此使用 [...arguments] 將arg 轉為陣列。 ```javascript= var originCash = 1000; function updateEasyCard() { let arg = [...arguments]; let sum = arg.reduce(function (accumulator, currentValue) { return accumulator + currentValue; }, 0); console.log('我有 ' + sum + ' 元'); } updateEasyCard(0); // 我有 1000 元 updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); // 我有 718 元 ``` ### 4. 其餘參數 - 有些時候傳入參數時,並不確定參數有多少,這時就可以使用到'其餘參數'。 - 下面的範例,money 的參數就會自動以陣列的方式呈現。 ```javascript= function moreMoney(...money) { console.log(money); //[100, 100, 100] } moreMoney(100, 100, 100) ``` - 也可以前面有變數,後面不確定數量的值使用其餘參數。 ```javascript= function moreMoney(ming,...money) { console.log(ming); //小明 console.log(money); //[100, 100, 100] } moreMoney('小明',100, 100, 100) ``` # 肆、解構賦值 ### 1. 賦值 - 原本使用 ES5 時,將陣列的值拿出來賦於另一個變數要這樣做 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽', '老爸']; let ming = family[0]; let jay = family[1]; let auntie = family[2]; ``` - 如果使用 ES6 解構賦值的特性,變數就可以被快速賦值上去 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽', '老爸']; let [ ming , jay , aunt , mom , dad ]= family; console.log(ming , jay , aunt , mom , dad); //小明 杰倫 阿姨 老媽 老爸 ``` - 假如左右數量不對等時,就只會呈現左方出現變數的名稱 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽', '老爸']; let [ ming , jay , aunt]= family; console.log(ming , jay , aunt); //小明 杰倫 阿姨 ``` - 當中間值有缺少時,阿姨的值就不會進行解構賦值 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽', '老爸']; let [ ming , jay ,, mom , dad ]= family; console.log(ming , jay , mom , dad); ``` - 設定預設值:當 value 有缺少時,可以使用預設值來填補 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽']; let [ ming , jay , aunt , mom , dad='老爸' ]= family; console.log(ming , jay ,aunt , mom , dad); // 小明 杰倫 阿姨 老媽 老爸 ``` - 其餘部分:可以其餘剩餘的部分放在...other 裡面 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽']; let [ ming , ...other ]= family; console.log(ming , other); //小明 ["杰倫", "阿姨", "老媽"] ``` - 忽略元素: 單獨要取某個值時,可以使用,數量來取得 ```javascript= let family = ['小明', '杰倫', '阿姨', '老媽']; let [ ,, aunt]= family; console.log(aunt); // 阿姨 ``` ### 2. 使用解構賦值來交換兩個變數的內容 ```javascript= let Goku = '悟空'; let Ginyu = '基紐'; [ Goku , Ginyu ] = [ Ginyu , Goku ] console.log(Goku,Ginyu);//基紐 悟空 ``` ### 3. 使用解構賦值將字串的一個個字元取出來 ```javascript= let str = '基紐特攻隊'; let [a,b,c,d,e] = str; console.log(a,b,c,d,e); //基 紐 特 攻 隊 ``` ### 4. 取出其中一個值,並附在新的變數名稱上 將 Ginyu 的變數替換為 Guku ```javascript= let GinyuTeam = { Ginyu: '基紐', Jeice: '吉斯', burter: '巴特', // ... } let {Ginyu:Guku} = GinyuTeam; console.log(Guku); //基紐 ``` ### 5. 請取出物件內的兩個值到單一變數上 淺拷貝 ```javascript= let family = { ming: '小明', jay: '杰倫', }; let familyAll = { ...family } console.log(familyAll); //{ming: "小明", jay: "杰倫"} ``` ### 6. 延伸問題 ```javascript= let { ming: Goku, family: [, mom] } = { ming: '小明', family: ['阿姨', '老媽', '老爸'] } console.log(Goku, mom); // 小明 老媽 ``` ### 7. 預設值的概念 ```javascript= let [ming = '小明', jay = '杰倫'] = ['阿明'] // 第一個會被賦值,第二個會用預設 console.log(ming,jay); //阿明 杰倫 ``` ### 8. 替換加上預設值 ```javascript= let { family: ming = '小明' } = {family:'小強'} console.log(ming) //小明 ``` ### 9. 解構函式參數: 再帶入參數值時,直接將物件解構 ```javascript= // function distance(point){ // const [x, y] = point // return Math.sqrt(x*x+y*y); // } function distance([x, y]){ return Math.sqrt(x*x+y*y); } const point = [1, 3] distance(point); ``` # 伍、縮寫 ### 1. 請將以下兩個合併至一個物件上 - 這時,如果賦值的變數是一樣的,就可以不重複寫。 - 這邊的屬性有淺拷貝 ```javascript= const Frieza = '弗利沙' const GinyuTeam = { Ginyu: '基紐', Jeice: '吉斯', burter: '巴特', // ... } const newTeam = { Frieza : Frieza, -> Frieza, GinyuTeam : GinyuTeam -> GinyuTeam } console.log(newTeam); ``` ### 2. 物件函式的縮寫 只能用在物件內喔。 ```javascript= const newTeam = { // ... showPosture: function () { console.log('我們是 基紐特戰隊') } } newTeam.showPosture(); //可以改成 const newTeam = { // ... showPosture() { console.log('我們是 基紐特戰隊') } } newTeam.showPosture(); ``` ### 3. 搭配解構使用縮寫 原本只有使用縮寫,會再包一層 ```javascript= const GinyuTeam = { Ginyu: { name: '基紐' }, Jeice: { name: '吉斯' }, burter: { name: '巴特' }, // ... } const newTeam = { GinyuTeam,////<----------只有縮寫,這邊有淺拷貝 } newTeam.ming="小明"; console.log('newTeam',newTeam,'GinyuTeam',GinyuTeam) ``` ![](https://i.imgur.com/XENh75g.png) 搭配解構後 ```javascript= const GinyuTeam = { Ginyu: { name: '基紐' }, Jeice: { name: '吉斯' }, burter: { name: '巴特' }, // ... } const newTeam = { ...GinyuTeam,////<----------搭配解構 } newTeam.ming="小明"; console.log('newTeam',newTeam,'GinyuTeam',GinyuTeam) ``` ![](https://i.imgur.com/bry38v4.png) # 陸、箭頭函示與傳統函式 ### 1. 基本的箭頭函式 ```javascript= var callSomeone = (someone) => { return someone + '吃飯了' } console.log(callSomeone('小明')) ``` - 如果函式內榮只有一行就可以再簡化,把 ()、return、{} 花括號拿掉 ```javascript= var callSomeone = someone => someone + '吃飯了' console.log(callSomeone('小明')) ``` - 如果預期不帶入參數,()就不能省略 ```javascript= var callSomeone = () => someone + '吃飯了' console.log(callSomeone()) ``` ### 2. 箭頭函式裡面沒有 argument 這個參數 ```javascript= const updateEasyCard = () => { let cash = 0; console.log(argument); // arguments is not defined } updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); //不能執行,箭頭函式裡面沒有 argument 這個參數 ``` - 要改寫為其餘參數 ```javascript= const updateEasyCard = (...arg) => { let cash = 0; console.log(arg); // arguments is not defined } updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); ``` ### 3. 箭頭函式裡面的 this 都會指向全域變數 ### 4. 在 Vue 的 methods 裡面使用傳統函式,可以使用縮寫的方式 # 柒、字串模板 Template String ### 1. ${ } 放入的是表達式 表達式是什麼? 表達式是一段可以很長,但會產生結果值的程式碼,而且很常是運算式 ```javascript= 1 + 2 functionInvocation() ture || false d true && true a = 3 //會回傳 3 a === 3 Array.isArray([]) ? doSomeThing() : doOtherThing() ``` 陳述式是什麼? 陳述式一定會做一些事情,但陳述式不會產生數值 下面這些都是 JavaScritp 裡的陳述式: - 變數宣告 - if 判斷式 - while 迴圈 - for 迴圈 - switch 判斷是 - for-in 迴圈 - 直接的函式宣告 ```javascript= var a = 3 ; if(a === 3){ //doSomeThing... } { //doSomeThing , this is a Block Statement } for (var i = 0 ; i<=10 ; i++ ){ //doSomeThing } try{ ... }catch (){ ... } ``` 使用表達式的範例 ```javascript= // 在 ${} 內直接做運算 function greet(name, days){ // const hours = days*24; console.log(`Hello, ${name}. It's been ${days*24} hours`) } greet('Jack', 3) // 在 ${} 內做三元判斷式 function greet(name, days){ console.log(`Hello, ${name}. ${(days < 7)?'':'Long time no see'}) } greet('Jack', 3) // Hello, Jack. greet('Mary', 14) // Hello, Mary. Long time no see ``` ### 2. 字串模板裡面也可以寫 JavaScript ```javascript= const people = [ { name: '小明', friends: 2 }, { name: '阿姨', friends: 999 }, { name: '杰倫', friends: 0 } ] let originUl = ` <ul> ${people.map(item => `<li>我叫做 ${ item.name }</li>`).join('')} </ul>`; console.log(originUl); ``` # 捌、操作陣列的方法 ### 1. foreach - foreach 的功能跟 for 迴圈是一樣的。一樣會把陣列全部跑一遍。 **array.forEach(function(item, index, array){...}** item: 陣列中的物件 index: 索引 array: 整個陣列 ```javascript= const people = [ { name: '小明', money: 500 }, { name: '漂亮阿姨', money: 3000 }, { name: '杰倫', money: 60000 }, { name: '老媽', money: Infinity } ]; people.forEach(function(item, index, array){ item.cash = item.money + 500; console.log(item); }) ``` ### 2. map - map 的作用基本和 foreach 一樣。但 map 會有 return 回傳值。 ```javascript= const people = [ { name: '小明', money: 500 }, { name: '漂亮阿姨', money: 3000 }, { name: '杰倫', money: 60000 }, { name: '老媽', money: Infinity } ]; people.map(function(item, index, array){//只是把 foreach 改 map item.cash = item.money + 500; console.log(item); }) ``` - 唯一不同的是,他會回傳值。回傳的值可以變成一個新的陣列。 ```javascript= //回傳一個新的陣列 const newPeople1 = people.map(function(item, index, array){ return item; }) console.log(newPeople2); ``` - 如果沒有使用展開,回傳的陣列中,people 的物件會另外被包在 item 的物件裡面, icash則獨立分開。 ```javascript= //回傳一個新的陣列,並加入 icash const newPeople2 = people.map(function(item, index, array){ return{ item, icash : item.money+500, } }) console.log(newPeople); ``` ![](https://i.imgur.com/V0yq00j.png) - 使用展開後,所有的資料都會並列在同一個陣列裡面。 ```javascript= //回傳一個新的陣列,並加入 icash const newPeople3 = people.map(function(item, index, array){ return{ ...item, icash : item.money+500, } }) console.log(newPeople1); ``` ![](https://i.imgur.com/Y8gJEbV.png) - map **不適合**用來過濾陣列,因為有沒有符合條件,他都會 return 值,沒符合條件傳回來的值會變成 undefined。 ```javascript= const newPeople = people.map(function(item, index, array){ if(item.money > 500){ return{ ...item, } } }) console.log(newPeople); ``` ![](https://i.imgur.com/6DSspS8.png) ### 3. filter - filter 用來過濾條件為 true 的值。 ```javascript= const filterArr = people.filter(function(item,index){ if(item.money < 5000){ return true; } //也可以改寫為 return item.money < 5000 }) console.log(filterArr); //{name: "小明", money: 500} {name: "漂亮阿姨", money: 3000} ``` ### 4. find 適合用來尋找單一條件, find 只會回傳一個值。像找 id 等特定值就很適合。 ```javascript= const findArr = people.find(function(item,index){ if(item.money < 5000){ return true; } }) console.log(findArr); //{name: "小明", money: 500} ``` ### 5. every - 回傳值只回 true 或 false。 - 回傳 true 的條件必須是所有值都滿足條件,否則回傳 false ```javascript= const ans = people.every(function(item,index){ return item.money >3000; }) console.log(ans); // false ``` ### 6. some - 回傳值只回 true 或 false。 - 回傳 true 的條件最少只要有一個值滿足條件,全部不符則回傳 false ```javascript= const ans = people.some(function(item,index){ return item.money >3000; }) console.log(ans); //true ``` ### 7. reduce reduce(function(prev,item,index){...}, default) prev: 前一個值,如果沒有前一個值就使用 default item: 目前的值 index: 索引 ```javascript= const people = [ { name: '小明', money: 500 }, { name: '漂亮阿姨', money: 3000 }, { name: '杰倫', money: 60000 } ]; const num = people.reduce(function(prev,item,index){ console.log(prev); return prev+item.money; },0) console.log(num); //0(prev) //500(prev) //3500(prev) //63500(num) ``` - 使用 reduce 做比大小的運用 ```javascript= const num = people.reduce(function(prev,item,index){ console.log(prev); return Math.max(prev,item.money); //拿前一個值和目前值比較大小 },0) console.log('Max:',num); ```