JavaScript ES6 介紹

Share This Post

歷史介紹

  • ECMAScript 6 (簡稱 ES6),是 JavaScript 語言新一代的標準,在 2015 年 6 月正式發佈。
  • ES6 其實是一個泛指的名詞,泛指 ES5.1 版以後的新一代 JavaScript 語言標準,涵蓋了 ES2015, ES2016, ES2017 等等,ES2015 則是正式名稱,特指該年度發佈的語言標準,現在常聽到人家說的 ES6,一般是指 ES2015 標準。
  • ES6 提出了很多新的語法,使得 JavaScript 變得更強大,更適合用來寫大型的應用程式!
  • ES6 新增的則是一些寫法上的改變,讓寫法變得更精簡,以及新增了非同步專用的 Promise 、 JS 模組化必備的 ES6 Modules 、 Classes

以下是 ES6 新的特性:

功能介紹

1. Block Scope 塊級作用域 – let, const

在 ES6 之前,JavaScript 用 var 關鍵字來宣告一個變數,其作用範圍是 function scope,在 ES6 中引入了兩個新的語法 let 和 const 讓你可以宣告塊級作用範圍 (block scope) 的變數。

所謂的 block scope 就是變數的作用範圍只存在兩個大括號 { } 中。

let

let 關鍵字用來宣告一個 block scope 變數。

  • let 可以宣告只能在目前區塊、階段或表達式中作用的變數。
  • 而 var 則是定義了一個全域變數,或是在整個 function 而不管該區塊範圍。
functionvarTest(){var x =1;{var x =2;// 這裡的 x 與 function 區塊內部的 x 是一樣的,因此會影響 function 區塊內所有的 x
    console.log(x);// 2}
  console.log(x);// 2}functionletTest(){let x =1;{let x =2;// 這裡的 x 與 function 區塊內部的 x 是不同的,只會作用在這層 block 區塊中
    console.log(x);// 2}
  console.log(x);// 1}

在上列例子裡的最前行 let 和 var 不同,let 並不會在全域物件中建立變數。舉例來說:

var x ='global';let y ='global';
console.log(this.x);// "global"
console.log(this.y);// undefined

const 常數

const 關鍵字跟 let 類似,也可以用來宣告一個 block scope 變數,不同的是,const 宣告的變數其指向的值不能再被改變。

{constA=10;// 會發生錯誤,常數值不能再被改變// TypeError: Assignment to constant variableA=10;// 陣列是一個有趣的例子constARR=[1,2];// 可以改變陣列裡的內容// 因為 ARR 變數值沒有改變,還是指向同一個陣列ARR.push(3);// [1, 2, 3]
    console.log(ARR);// 錯誤,不能改常數值// TypeError: Assignment to constant variableARR=123;// 但可以改變陣列裡面的內容ARR[0]=4;// [4, 2, 3]
    console.log(ARR);}

2. JavaScript ES6 Arrow Functions 箭頭函數

ES6 允許我們用箭頭 => 來更方便簡短的定義一個函數,這種語法稱作 Arrow Functions。

Arrow Functions 由參數列 (…) 接著 => 和函數內容所組成。

// 原始樣貌 function(){};// ES6=()=>{};

例1:

// 傳統標準的函數宣告語法varmultiply=function(a, b){return a * b;};// 使用 Arrow Functions 的語法varmultiply=(a, b)=> a * b;// 20multiply(2,10)

例2:

let numbers =[1,2,3];// callback 用 Arrow Functions 的寫法更精簡let doubles = numbers.map(num=>{return num *2;});// [2, 4, 6]
console.log(doubles);

3. JavaScript ES6 Default Function Parameters

在 ES6 中,JavaScript 函數的參數終於可以有預設值了。

// 傳統寫法functionmultiply(a, b){
  b =(typeof b !=='undefined')?  b :1;return a * b;}multiply(5,2);// 10multiply(5,1);// 5multiply(5);// 5// ES6寫法multiply=(a, b = 1)=>{return a * b;}multiply(5,2);// 10multiply(5,1);// 5multiply(5);// 5

4. JavaScript ES6 Spread/Rest Operator 運算子

ES6 引入了新的運算子 (operator) … (三個點號) 來表示展開或其餘運算子。

Spread Operator 展開運算子

Spread Operator 可以用在執行函數時的參數列上,它可以將一個陣列 (array) 展開,轉為多個逗點隔開的獨立參數:

範例:

// 例1functionfoo(x, y, z){
    console.log(x, y, z);}var arr =[1,2,3];// 輸出 1 2 3// 等同於執行 foo(1, 2, 3)foo(...arr);// 例2functionfoo2(a, b, c, d, e){
    console.log(a, b, c, d, e);}var arr2 =[3,4];// 輸出 1 2 3 4 5// 等同於執行 foo(1, 2, 3, 4, 5)foo(1,2,...arr2,5);// 例3var parts =['shoulders','knees'];// 將 parts 展開在 lyrics 的元素中var lyrics =['head',...parts,'and','toes'];// lyrics 的值會變成 ["head", "shoulders", "knees", "and", "toes"]// 例4 var ary1 =[4,5,6];var ary2 =[1,2,3];// ary1 會變成 [1, 2, 3, 4, 5, 6]
ary1 =[...ary2,...ary1];

5. JavaScript ES6 Object Literal Extensions 物件實字的擴展

ES6 的新語法讓 object literal 可以寫得更簡短清楚。

如果屬性名稱和變數名稱一樣,可以在物件裡面只使用變數,變數的名城也會被當作是屬性名稱,而變數的值會被當作屬性值。

用法:

var obj ={
    foo,
    bar
};

上面的語法同等於:

var obj ={foo: foo,bar: bar
};

Computed property keys 計算得出的屬性名稱

ES6 允許使用表達式 (expression) 作為屬性的名稱,語法是將 expression 放在中括號 [ ] 裡面,透過 [ ] 的語法,我們的屬性名稱就可以放入變數,達到動態產生屬性名稱的效果。

var prefix ='es6';var obj ={// 計算屬性[prefix +' is']:'cool',// 計算方法[prefix +' score'](){
        console.log(100);}};// 顯示 cool
console.log(obj['es6 is']);// 顯示 100
obj['es6 score']();

6. JavaScript ES6 Octal/Binary Literals 八進位/二進位表示法

ES6 支援 octal literal 和 binary literal。
可以直接輸入下方兩種樣式
二進位表示法 0b 或 0B 表示。
八進位表示法0o 或 0O 表示。

var oValue =0o10;// 8
console.log(oValue);var bValue =0b10;// 2
console.log(bValue);

7. JavaScript ES6 Array and Object Destructuring Assignment 陣列和物件的解構賦值

ES6 的 destructuring assignment,可以用來從陣列或物件中抽取 (destructuring) 值出來指定 (assignment) 給變數。

ES6以前 在給予值只能用指定的方式

var one ='one';var two ='two';var three ='three';

現在 ES6的寫法

var foo =["four","five","six"];var[four, five, six]= foo;// 從 array 中提取值,然後按照對應的位置,指定給相應的變數// "four"
console.log(four);// "five"
console.log(five);// "six"
console.log(six);

只要結構一樣,就能取得對應的值

var obj ={p:['Hello',{y:'World'}]};var{p:[x,{y}]}= obj;// "Hello"
console.log(x);// "World"
console.log(y);
const obj ={name: apple,age:20,birthday:2000/01/01}// 傳統寫法const name = obj.name;const age = obj.age;const birthday = obj.birthday;// "apple , 20 , 2000/01/01"
console.log(name,age,birthday);// ES寫法 ,前提是要名稱一模一樣const{ name , age , birthday }= obj;// "apple , 20 , 2000/01/01"
console.log(name,age,birthday);

8. JavaScript ES6 super Keyword

在 ES6 中新增的 super 關鍵字 (keyword),在物件的方法 (method) 中使用時,super 會指向父類別 (的 prototype),方便我們可以存取父類別中的。

只能用在ES6新的方法中,如果放在傳統的 function 會出錯。
// Uncaught SyntaxError: ‘super’ keyword unexpected here

var parent ={foo(){
        console.log('Hello from the Parent');// 2},a:'a of parent'// 4}var child ={foo(){
        console.log('Hello from the child');// 1super.foo();
        
        console.log(this.a);
        console.log(super.a)},a:'a of child'// 3}

Object.setPrototypeOf(child, parent);

child.foo();

接著會依序列出

Hello from the child
Hello from the Parent
a of child
a of parent

9. JavaScript ES6 Template Literals 字串樣版

ES6 引入了 Template Literals (字串樣版) 是增強版的字串表示法,Template Literals 讓你可以寫多行字串 (multi-line strings)、也可以在字串中插入變數或 JavaScript 表達式 (String/Expression interpolation)。

Template Literals 的語法是用兩個反引號 (back-tick) `` 標示,而在字串中可以使用 ${ } 語法來嵌入變數或 JavaScript 表達式。

// 傳統的寫法:var str ='string text line 1\n'+'string text line 2'// Template Literals 新的寫法:var str =`string text line 1 
string text line 2`

嵌入變數或任何表達式 String/Expression Interpolation

傳統的寫法 都必須一直使用 + 跟’’來組合物件

var a =5;var b =10;
console.log('Fifteen is '+(a + b)+' and\nnot '+(2* a + b)+'.');

ES6的寫法直觀很多

var a =5;var b =10;
console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`);

10. JavaScript ES6 for…of 迴圈

在 ES6 之前,有幾種迴圈的寫法可以遍歷一個陣列:

  1. for 迴圈
  2. for…in 迴圈
  3. forEach 方法

最一開始的for 迴圈寫起來過於冗長,所以ES5 使用forEach來簡化迴圈,但有個缺點是不能使用 break 來中斷迴圈,或用 return 直接返回迴圈最外層

ES6 新的 for…of 語法有什麼好處:

  1. 更簡潔直觀的語法
  2. 沒有 for…in 的缺點
  3. 跟 forEach 不同的是 for…of 可以搭配 break, continue, return 語句
  4. for…of 支持遍歷更多的集合類型,像是 string, Map, Set…
let number =[10,20,30];for(let value of number){
    value +=1;
    console.log(value);}// 依序輸出// 11// 21// 31

11. JavaScript ES6 Map and WeakMap Object 物件

ES6 新增了 Map 和 WeakMap 數據結構。

Map
Map 有點像是 object (key-value pairs),兩者不同的地方在於 object 的 key 只能是字串 (string);而 Map 的 key 則可以是任何的資料型態!

另外 Map 中的資料是有序的,當你遍歷一個 Map 資料結構時,會依照 key-value pairs 先前寫入的順序 (insertion order)。

建立 Map 物件的語法:

// 建立一個空 MapnewMap()// 建立一個 Map 並初始化newMap(iterable)

使用範例

// 建立一個 Map 物件
var myMap = new Map();

var keyString = 'a string';
var keyObj = {};
var keyFunc = function() {};

// set() 用來新增 key-value pair

// key 不限字串,可以是任何的資料型態
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, 'value associated with keyObj');
myMap.set(keyFunc, 'value associated with keyFunc');

// get() 用來取得某個 key 的值

// 顯示 "value associated with 'a string'"
console.log( myMap.get(keyString) );
// 顯示 "value associated with keyObj"
console.log( myMap.get(keyObj) );
// 顯示 "value associated with keyFunc"
console.log( myMap.get(keyFunc) );

// 因為 keyString === 'a string'
// 顯示 "value associated with 'a string'"
console.log( myMap.get('a string') );

// 因為 because keyObj !== {}
// 顯示 undefined
console.log( myMap.get({}) );

// 因為 keyFunc !== function () {}
// 顯示 undefined
console.log( myMap.get(function() {}) );

12. JavaScript ES6 Set and WeakSet Object 物件

ES6 新增了 Set 和 WeakSet 數據結構。

Set

Set 有點像是陣列 (array),Set 中的元素 (element) 可以是任何資料型態,兩者不同的地方在於 Set 中所有的值都是唯一的 (unique values),不會有重複的值,當你存入重複值 (duplicate values) 會被忽略。

當你向 Set 中加入新元素時,Set 內部會用 === 來判斷是否有重複值,唯一的例外是 NaN 會被判斷作是重複的值,雖然 NaN !== NaN。

Set.prototype.size

用來取得 Set 物件的大小,總共有幾個元素。

var mySet = new Set();

mySet.add(1);
mySet.add(5);
mySet.add('some text')

// 3
mySet.size;

Set.prototype.add(value)

用來新增元素,add() 方法會返回 Set 本身。

var mySet = new Set();

mySet.add(1);
mySet.add(5)
mySet.add('some text');

// Set {1, 5, "some text"}
mySet;

Set.prototype.has(value)

返回一個 boolean,判斷 Set 中有沒某個值。

var mySet = new Set();
mySet.add('foo');

// true
mySet.has('foo');
// false
mySet.has('bar');

13. JavaScript ES6 class 關鍵字

在 ES6 中,引入了 Class (類別) 這個新的概念,透過 class 這新的關鍵字,可以定義類別。

另外還引入了一些其他的新語法,來讓你更簡單直觀的用 JavaScript 寫 OOP (物件導向) 程式,但大多數語法只是語法糖 (syntactical sugar),並不是重新設計一套物件繼承模型 (object-oriented inheritance model),只是讓使用者更方便操作 JavaScript 既有的原型繼承模型 (prototype-based inheritance)。

可以用 class 語法定義一個類別:

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

也可以用extends 關鍵字用作類別繼承:

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

class Dog extends Animal {
    speak() {
        console.log(this.name + ' barks.');
    }
}

var d = new Dog('Mitzie');

// 顯示 Mitzie barks.
d.speak();

14. JavaScript ES6 Promise Object 物件

Promise 是一種非同步 (asynchronous) 編程的解決方案,所謂的 Promise,簡單來說它是一個等待非同步操作完成的物件,當事件完成時,Promise 根據操作結果是成功、或者失敗,做相對應的處理動作。

一個 Promise 物件 (只) 會處於下面三種狀態之一:

pending – 初始狀態 (進行中)
fulfilled – 事件已完成
rejected – 事件已失敗

Promise 狀態的改變只有兩種可能:

從 pending 變成 fulfilled
從 pending 變成 rejected

範例

var promise = new Promise(function(resolve, reject) {

  // ...
  
  if (異步操作成功) {
    resolve(value);
  } else {
    reject(error);
  }

});

訂閱研究文章

Get updates and learn from the best

More To Explore

Scroll to Top

hurry up !

軟體工程師培訓

限時免費報名中

藉由與「真實世界軟體專案」相同的技術、工具與開發流程,化簡成與商業機密無關、門檻較低更容易上手的「模擬專案」,讓你有機會在職場前輩的陪伴下,完成真槍實彈的練習,動手解決真實的問題,快速累積個人的經驗與作品,而不只是「學習技術」而已。