# ES6 新功能 ###### tags: `javascript` ES6:ECMAScript 6 > doku wiki 支援的markdown so 糟糕,所以連結和圖片會跑掉.... ## 參數預設值(Default Parameters) [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters "Default Parameters") * 功能:在function接受參數時,可以給預設值,避免出現error。 * Example: * 原本的寫法: ```javascript function f ( pa, pb ) { if ( pb === undefined ) pb = 10; return pa + pb; } ``` * 可以改寫成這樣: ```javascript function f ( pa, pb = 10) { return pa + pb; } ``` ## 變數宣告: `let` and `const` * 功能:在ES6之前,變數選告只能使用`var`做宣告,[so糟糕](https://ithelp.ithome.com.tw/articles/10203548)。 * `let`:只會在目前的`{}`內有效,若重複定義會throw error。 [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let "let") * `const`:一樣只會在目前的`{}`內有效,須給初始值,且值不可更改。 [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const "const") * Example 1: ```javascript function f ( ) { let v = 1; console.log ( v ); // output: 1 if ( true ) { let v = "another instance"; console.log ( v ); // output: "another instance" } let v = 123; // Uncaught SyntaxError: Identifier 'v' has already been declared } console.log( v ); // Uncaught ReferenceError: v is not defined ``` * Example 2: ```javascript function f ( ) { const newConst; // Uncaught SyntaxError: Missing initializer in const declaration const newConst2 = 0; console.log ( newConst2 ); // output: 0 newConst2 = 2; // Uncaught TypeError: Assignment to constant variable } console.log ( newConst2 ); // Uncaught ReferenceError: newConst2 is not defined ``` ## 模板字串(Template Literals):`` `${}` `` [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals "Template Literals") * 功能: * 在ES6之前,要把多個變數和字串組在一起變成一個大字串只能用`+`來完成。現在可以在一行寫完。 * 在ES6之前,假如有一個字串有很多行,都需要在行尾加上`\`才會運作。現在可以不用管這件事了。 * 用法: * 模板字串的頭尾使用反引號(`` ` ``)框起來,若中間有需要變數則使用`${}`並把變數放在`{}`裡面。 * 若有多行字串就照打下去就好了,不用管。 * Example 1: * 原本的寫法: ```javascript function f ( ) { let i = "I"; let l = "hate"; let j = "JavaScript"; console.log ( i + " " + l + " " + j + "." ); // output: "I hate JavaScript." } ``` * 可以改寫成這樣: ```javascript function f ( pa, pb = 10) { let i = "I"; let l = "hate"; let j = "JavaScript"; console.log ( `${i} ${l} ${j}` ); // output: "I hate JavaScript." } ``` * Example 2: * 原本的寫法: ```javascript function f ( ) { return ( " A \ Multiple \ Line \ String \ " ); } ``` * 可以改寫成這樣: ```javascript function f ( ) { return ( ` A Multiple Line String ` ); } ``` ## Spread Operatpor and Rest Parameters:`...` 這兩個長得一模一樣都是由三個句號所組成:`...`。 * Spread Operator [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax "Spread Syntax") : 用來解構Array和Object,看例子比較快。 * Example 1: Array 的解構 ```javascript function f ( pa, pb, pc, pd ) { console.log ( pa, pb, pc, pd ); } let a = [1, 2, 3, 4]; f ( ...a ); // output: 1 2 3 4 // 可以看成是 f ( a[0], a[1], a[2], a[3] ); ``` * Example 2: Array 的解構 ```javascript let arr1 = [1, 2] let arr2 = [3, 4]; let result1 = [arr1, arr2]; let result2 = [...arr1, ...arr2]; console.log ( result1 ); // output: [[1, 2], [3, 4]] console.log ( result2 ); // output: [1, 2, 3, 4] ``` * Example 3: Object 的解構 ```javascript let obj1 = { a: 2, b: 3 }; let obj2 = { c: 3, d: 4 } let result1 = {obj1, obj2}; let result2 = {...obj1, ...obj2}; console.log ( result1 ); // output: {obj1: {a: 2, b: 3}, obj2: {c: 3, d: 4}} console.log ( result2 ); // output: {a: 2, b: 3, c: 3, d: 4} ``` * Example 4: 用來object的key的預設值寫法,key重複會由最後面的決定其value(後面的會覆蓋前面的)。 ```javascript function f ( config ) { const defualtConfig = { configA: 1, configB: "", configC: null, configD: "Some default value", } config = { ...defaultConfig, ...config }; // Some other codes here } ``` * Rest Paramaters [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters "Rest Paramaters") : 如果 function 接受的參數數量不固定,可以使用 Rest Operator 把多個參數併成一個陣列。 _關於這個你也可以看看這個:[The arguments object ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments "The arguments object ")_ * Example: ```javascript function f ( pa, pb, ...r ) { console.log ( r ); } f ( 1, 2, 3, 4, 5, 6, 7 ); // output: [3, 4, 5, 6, 7] ``` ## 解構賦值(Destructuring Assignment)[![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment "Destructuring Assignment") ES6中從Array或Object取值的辦法,主要用`...`來完成。 * Example 1: Array * 原本的寫法: ```javascript let array = [1, 2, 3, 4]; let first = array [ 0 ]; let second = array [ 1 ]; let rest = array.slice(2); console.log ( array ); // output: [1, 2, 3, 4] console.log ( first ); // output: 1 console.log ( second ); // output: 2 console.log ( rest ); // output: [3, 4] ``` * ES6的寫法: ```javascript let array = [1, 2, 3, 4]; let [first, second, ...rest] = array; console.log ( array ); // output: [1, 2, 3, 4] console.log ( first ); // output: 1 console.log ( second ); // output: 2 console.log ( rest ); // output: [3, 4] ``` * Example 2: Object * 原本的寫法: ```javascript let circle = { border: "black", fill: "white", position_x: "2", position_y: "3" }; let border = circle.border; let fill = circle.fill; let radius = circle.radius || 1; console.log ( border ); // output: "black" console.log ( fill ); // output: "white" console.log ( radius ); // output: 1 ``` * ES6的寫法: ```javascript let circle = { border: "black", fill: "white", position_x: 2, position_y: 3 }; let { border, fill, radius = 1 } = circle; console.log ( border ); // output: "black" console.log ( fill ); // output: "white" console.log ( radius ); // output: 1 ``` ## 箭頭函式(Arrow Function)[![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions "Arrow Function") * 箭頭函式主要用來取代舊版的匿名函示,`()=>{}`。 * 箭頭函式與原本的function的差別在於: * 箭頭函式無法被`new`(為甚麼function可以被`new`?。 * 兩者的`this`指向不同(去看`this`那一篇的Lexical Binding。 * 新舊寫法對照: * 舊版寫法: ```javascript function ( /* put paramaters here, use comma to seperate them */ ) { // some code here return /* some return value here */; } ``` * 新版寫法 ```javascript ( /* put paramaters here, use comma to seperate */ ) => { // some code here return /* some return value here */; } ``` * 如果參數只有一個,則小括弧(`()`)可以省略。 * 如果後面的內容直接是回傳值,則大括弧(`{}`)和`return`可以省略。 * Example 1: * 舊版寫法: ```javascript let words = ['concat', 'filter', 'entries', 'findIndex', 'lastIndexOf', 'reduceRight', 'undefined', 'toLowerCase']; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter let results = words.filter ( function ( w ) { if ( w.length > 10 ) return true; else return false; } ); console.log ( results ); // output: ["lastIndexOf", "reduceRight", "toLowerCase"] ``` * 第一次改寫:先改寫成arrow function 的寫法 ```javascript let results = words.filter ( ( w ) => { if ( w.length > 10 ) return true; else return false; } ); ``` * 第二次改寫:因為參數只有一個,所以小括弧拿掉 ```javascript let results = words.filter ( w => { if ( w.length > 10 ) return true; else return false; } ); ``` * 第三次改寫:改寫`return`的部分 ```javascript let results = words.filter ( w => { return w.length > 10; } ); ``` * 最後改寫:因為內容的部分直接是`return`的部分,所以把大括弧和`return`拿掉。 ```javascript let results = words.filter ( w => w.length > 10 ); ``` * Example 2: 下面兩行code結果完全相同。 ```javascript let l = length.reduce( ( a, c ) => lcm ( a, c ), 1 ); let l = length.reduce( lcm, 1 ); ``` * Example 3: 來解讀看看吧 ```javascript // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf let func = arr => arr.filter ( ( e, i, a ) => a.indexOf ( e ) === i ); let array = [2, 3, 18, 5, 9, 0, 10, 5, 10, 3, 7, 9, 18]; let results = func ( array ); console.log ( results ); // output ? ``` ## `Class` [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes "Classes") ES6 開始支援`Class`。寫類別的時候更直覺也可以繼承。 * Example: ```javascript // 使用extends關鍵字來繼承其他的類別 Class Car extends Vehicle{ // constructor 是保留字,這個function就是建構式,類別剛建立的時候會做的事情。 constructor ( ) { // 使用super來call父類別的建構子 super ( ); } // 一般的function f ( ) { // some codes here return /* some return value */; } // 一個static function static f2 () { } } ``` ## `Promise` [![MDN web docs](https://developer.mozilla.org/static/img/favicon32.7f3da72dcea1.png)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises "Using promises") 就非同步嘛~有空再縮。 ## 參考資料 * JavaScript (ES6) Syntax 大集合:https://ithelp.ithome.com.tw/articles/10191712 * 淺談JS版本差異!ES5、ES6:https://ithelp.ithome.com.tw/articles/10206587 * [ES6] Javascript 開發者必須知道的 10 個新功能:https://medium.com/@peterchang_82818/es6-10-features-javascript-developer-must-know-98b9782bef44