# ES6,ES7,ES8

以下因Node.js版本不一定支援，所以可下載chrome canary並打開devtool輸入程式碼

許多比較新的js功能會在Chrome Canary開放

載點:<https://www.google.com.tw/chrome/browser/canary.html>

以下將會介紹比較常用到的幾種方法

## ES6

<https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_2015_support_in_Mozilla>

全名為`ECMAScript 6.0`或稱`ECMAScript 2015`

#### #const

用來定義常數，定義後不可更改

```
const a = 12;

然後輸入
a = 13;
將會產生錯誤
```

#### #let

一般變數的作用域是以function來區分，在同層function的同名變數如果重複給值，則會覆蓋前項，包含在if內，但如果if的同名變數是用let宣告，則不會影響到if外的變數

```
function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}
```

let的作用範圍會被侷限在if內，而不會改到外面的同名變數

#### #spread syntax

功能:把Array，以逗點分隔當成多個值

```
function myFunction(x, y, z) { console.log(x) }
var args = [0, 1, 2];
myFunction(...args); //相同於myFunction(1,2,3)
```

#### #Destructuring assignment(解構賦值)

功能:對應兩個Array或Object並把同名的值附上

```
var o = {p: 42, q: true};
var {p: foo, q: bar} = o;

console.log(foo); // 42 
console.log(bar); // true
```

```
let obj = {x: 1, y: 2}; let {x, y} = obj; // x = 1, y = 2
```

```
var a, b;

[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
```

#### #Arrow function

功能:簡化匿名function寫法，但會失去this屬性

```
//以前寫法
setTimeout(function(){ console.log('okok'),500});
//箭頭寫法
setTimeout(() => console.log('okok'),500);
```

#### #Object.assign()

功能:結合兩個物件

```
var obj = { a: 1 };
var copy = Object.assign({b: 12}, obj);
console.log(copy);
```

#### #Promise

1.new Promise傳入一個函數，該函數擁有兩個參數

2.這兩個參數均為函數，分別為resolve()和reject()

```
var promise = new Promise(function(resolve, reject) {
  //first execute 

  if (/* 如first execute成功 */){
    resolve(value);//發出resolve
  } else {
    reject(error);//發出reject
  }
});
```

4.使用resolve()代表成功，使用reject()代表first execute 部分沒成功，是否成功是由我們自己去判定寫邏輯

5.promise生成後可用then，執行成功或失敗鎖要執行的東西

```
promise.then(function(value) {
  // success//接收到resolve後會執行
}, function(value) {
  // failure //接收到reject後會執行
});
```

範例：

貼上以下範例，之後把改變`value = 1+2`即可看到console的改變

```
var promise = new Promise(function(resolve, reject) {
//first execute
var value = 1+1;
if (value === 2){
  resolve(value);//發出resolve
} else {
  reject(error);發出reject
}
});

promise
.then(function(value) {
  console.log('function被resolve了!')
})
.catch(function(err) {
  console.log(err)
})
```

#### #Promise.all

把許多promise的函式組成一個Array放入Promise.all內，當裡面每個都`resolve`或其中一個被`reject`時才會執行後面的then方法

```
Promise.all([promises...])
.then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});
```

#### #for of

```
let iterable = [10, 20, 30];

for (let value of iterable) {
  value += 1;
  console.log(value);
}
```

#### #Generator

功能:也是用來處理異步函式，讓他順序執行 不一樣的地方在於function後的星號，和`yield`

1\.

```
function* Fruit() {
  yield 'apple';
  yield 'banana';
  return 'ending';
}

var a = Fruit();
```

之後輸入a.next();

#### #class

說明:即為一般物件導向程式的class寫法，以前是用prototype的方法來寫繼承，有class後即可使用extend

1.類別如果有值或是其他建構時即擁有的屬性可寫在constructor

2.類別function 可直接寫出名字即可`speak() {}`

3.class繼承用extend

4.繼承後的子代必須先在constructor內寫`super()`之後才可用`this`

5.使用super存取父帶方法`super.IamParentMethod()`

```
class Cat { 
  constructor(name) { 
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' roars.');
  }
}
```

之後輸入`Lion.prototype`

#### export

我們在寫Node.js時使用的require是屬於CommonJS體系

但在ES6我們不使用require而使用import

(兩者亦可混合使用，參照webpack章節)

### 下面先介紹export用法

export用來輸出單個變數或function

```
export var fruit = 'apple';
export var person = 'John';

export function multiply (x, y) {
  return x * y;
};
```

也可寫成如下

```
var fruit = 'apple';
var person = 'John';

export {fruit,person,multiply};
```

可用as改變import時的名字

```
export {fruit as f,person as p,multiply as m};
```

最後

注意:export要放在function外不然會出錯

### 再來講import

```
import {fruit, person, multiply} from './list.js';
```

也可用as改變引入後的名稱

```
import {fruit as f, person as p, multiply as m} from './list.js';
```

也可一次載入

```
import * as list from './list.js';
```

### export default

上面的export方法在import時需要知道該變數名稱才可引用，為了解決，我們可使用export default

a.js

```
export default function () {
  console.log('I'm banana');
}
```

b.js

```
import customName from './a.js';//可自行指定名稱
customName(); // 'I'm banana'
```

我們在React通常會如下寫

```
// Component1.js
export default class { ... }

// main.js
import Component1 from './Component1.js'
```

## ES7

<https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_Next_support_in_Mozilla>

全名為`ECMAScript 7.0`或稱`ECMAScript 2016`

#### #Rest parameters destructuring

功能:動態指定參數個數

```
function fun1(...theArgs) {
console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3
```

#### #Array.includes

功能: 取得Array中是否包含某一個元素

```
var a = [1, 2, 3];
a.includes(2); // true 
a.includes(4); // false
```

## ES8

<https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_Next_support_in_Mozilla>

全名為`ECMAScript 8.0`或稱`ECMAScript 2017`

> Async與Await為ES8特性，但時常被誤以為是ES7

#### #Async與Await

可以簡單地在任何function前加上async字樣，之後把裡面會需要異步的function前加上await即可

後面用then()即可去進行步驟控制

```
async function getTrace () {  
    pageContent = await fetch('www.google.com', {
      method: 'get'
    })
  return pageContent
}

getTrace()  
  .then((data) => {
    console.log('----')
    console.log(data)
  })
```

#### #padEnd

功能：將字串補足位數至與第一個參數相同

```
'abc'.padEnd(10);         // "abc       "
'abc'.padEnd(10, "foo");  // "abcfoofoof"
'abc'.padEnd(6,"123456"); // "abc123"
```

#### #padStart

功能：將字串補足位數至與第一個參數相同，但方向為從頭開始

```
'abc'.padStart(10);         // "       abc"
'abc'.padStart(10, "foo");  // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
```

#### #Object.values

功能:取得所有物件中的值，以Array表示

```
var obj = { foo: "bar", baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
```

#### #Object.entries

功能:把物件中的key和value每組分別組成一個Array

```
var obj = { foo: "bar", baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://easonwang.gitbook.io/class/es6es7.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
