歷史介紹
- 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 之前,有幾種迴圈的寫法可以遍歷一個陣列:
- for 迴圈
- for…in 迴圈
- forEach 方法
最一開始的for 迴圈寫起來過於冗長,所以ES5 使用forEach來簡化迴圈,但有個缺點是不能使用 break 來中斷迴圈,或用 return 直接返回迴圈最外層
ES6 新的 for…of 語法有什麼好處:
- 更簡潔直觀的語法
- 沒有 for…in 的缺點
- 跟 forEach 不同的是 for…of 可以搭配 break, continue, return 語句
- 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);
}
});