---
# System prepended metadata

title: ES6 新功能
tags: [javascript]

---

# 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