ES6 Top Features You Must Know
02 Apr 2018ES6 快速小筆記。
let
/ const
- 兩者可完全取代
var
,用於限制作用域。 let
可被重新賦值;const
不可被重新賦值,但可更新。
可參考之前的文章-ES6: let, const, Block-Level Scope。
var
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log('exit from the for loop: ' + i);
0;
1;
2;
('exit from the for loop: 3');
let
過去 JavaScript 僅有 function 來實現作用域的限制,但 let 可讓作用域限於大括號內(Block-Level Declarations)。
出了作用域之後,i
變成沒有宣告卻要使用的變數,因此出現 ReferenceError。
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log('exit from the for loop: ' + i);
0
1
2
Uncaught ReferenceError: i is not defined
const
宣告變數為常數,不可重新賦值。
for (const i = 0; i < 3; i++) {
console.log(i);
}
console.log('exit from the for loop: ' + i);
0
Uncaught TypeError: Assignment to constant variable.
物件縮寫 Object Shorthand
原本的寫法
- 在屬性上是 key-value pair。
- 在方法上使用 function 關鍵字。
var foo = {
name: name,
getName: function() {},
};
物件縮寫後
- 屬性簡寫,若只有 key 而沒有 value,那麼就把 key 當成 value。注意,若屬性名稱是動態計算後得到的,則不可使用簡寫。
- 在方法上不需要 function 關鍵字。
const foo = {
name,
getName() {},
};
預設傳入參數 Default Paramaters
在 JavaScript 中,函式的參數預設值都為 undefined,在 ES6 可為參數設定初始值,好處是再也不用在函式中檢查參數是否為 undefined 後設定初始值了。
像是這樣的檢查,若傳入值是 undefined 再設定初始值…
function callMe(phone) {
var telNumber = typeof phone !== 'undefined' ? phone : '0912345678';
return telNumber;
}
callMe(); // "0912345678"
calMe('0987654321'); // "0987654321"
或
function callMe(phone) {
var telNumber = phone !== undefined ? phone : '0912345678';
return telNumber;
}
callMe(); // "0912345678"
calMe('0987654321'); // "0987654321"
現在可在參數傳入時,就來設定若為 undefined 時要給初始值…省去好多程式碼
const callMe = (phone = '0911111111') => phone;
callMe(); // "0911111111"
callMe('0922222222'); // "0922222222"
解構賦值 Destructuring Assignment
物件與陣列專用,類似鏡子映射的概念來指定成員值。
const [a, b] = [1, 2]; // a = 1, b = 2
const { foo, bar } = { foo: '12345' }; // foo = '12345', bar = undefined
字串模板 String Template
使用 ${ variable_name }
即可代入變數,而不需再用 +
與雙/單引號拼湊字串。
let name = 'Summer';
let greetings_1 = 'Hello ' + name + '!'; // greetings_1 = "Hello Summer!"
let greetings_2 = `Hello ${name}!`; // greetings_2 = "Hello Summer!"
擴展運算子 Spread Operator
以 ...
表示,將陣列展開成個別數值,可以想像是展示(展示這個陣列的所有元素)的功能。
範例。
let list = ['apple', 'boy', 'cat'];
console.log(...list); // apple boy cat
相關應用有…
陣列的複製,備註:多維陣列或有複雜物件結構的情況時,是以淺拷貝(Shallow Copy)的方式進行複製,下有範例。
let list = ['apple', 'boy', 'cat'];
let list2 = [...list];
let list3 = ['doll', ...list, 'fat'];
console.log(list2); // ["apple", "boy", "cat"]
console.log(list3); // ["doll", "apple", "boy", "cat", "fat"]
陣列的合併。
let list = ['apple', 'boy', 'cat'];
let list4 = ['george', 'happy', 'ice cream'];
let list5 = [...list, ...list4];
console.log(list5); // ["apple", "boy", "cat", "george", "happy", "ice cream"]
展開字串成為個別元素。
let list6 = [...'jacket'];
console.log(list6); // ["j", "a", "c", "k", "e", "t"]
當成參數,代入函式中。
let student = ['Nina', 'girl'];
function sayHi(name, gender) {
console.log(`Hi, I am ${name}. I am a ${gender}.`);
}
sayHi(...student); // Hi, I am Nina. I am a girl.
對照 ES5 的語法,由於 apply 的第二個參數是陣列(fun.apply(thisArg, [argsArray])
),因此上面的例子可改為下面的寫法
sayHi.apply(null, student); // Hi, I am Nina. I am a girl.
前面提到在多維陣列或有複雜物件結構的情況下,陣列的拷貝是屬於淺拷貝,這裡舉個例子。
兩個陣列並分別設定其初始值。
const list_1 = [{ a: 1 }, { b: 2 }, { c: 3 }, { d: { e: 4 } }];
const list_2 = [...list_1];
修改 list_1 其中一個深層元素的值,從 4 改成 5。
list_1[3].d.e = 5;
list_2 的這個深層元素的值也改變了,意即存的是參考位置而已,也就是淺拷貝。
list_2[3].d.e; // 5
其餘運算子 Rest Operator
以 ...
表示,集合剩餘的數值並轉為陣列,可以想像是收納(多個元素至一個陣列)的功能。
其餘參數。
const concatenate = (...letters) => {
let result = '';
letters.forEach((element) => {
result = `${result}${element}`;
});
return result;
};
concatenate('f', 'i', 'v', 'e'); // "five"
concatenate('s', 'i', 'x'); // "six"
在不確定要傳入多少參數的時候,是很好用的。
備註
- 其餘參數只能有一個,並且只能放在最後。
- 其餘參數在沒有傳入值的時候會是空陣列。
陣列的解構賦值。
const [a, ...b] = [1, 2, 3, 4, 5]; // a = 1, b = [2, 3, 4, 5]
同樣的,對應不到的時候就是空陣列。
const [a, ...b] = [1]; // a = 1, b = []
備註:用於物件上的語法請見 Rest/Spread Properties for ECMAScript。
箭頭函數 Arrow Function
const fun_1 = (x) => x;
fun_1(5); // 5
const fun_2 = (x, y) => x + y;
fun_2(1, 5); // 6
const fun_3 = (x, y) => {
z = x + y;
return z;
};
fun_3(2, 6); // 8
從 this 看不適合使用 Arrow Function 的時機
Arrow Function 內的 this 即為執行環境,且 this 的值無法被 bind、apply、call 等方法改變,因此以下狀況不適用 Arrow Function
- 在 addEventListener 的 callback 若使用 Arrow Function,this 可能會被設定為 window,而非「觸發事件的 DOM Element」。
- vue.js 的 method 利用 this 存取 data。
Class
處理 Prototype 繼承的語法糖,作用是提供更簡潔的方式來建立物件和處理繼承。
class People {
constructor(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
sayHi() {
console.log(`Hi, I am ${this.name}.`);
}
}
// HappyPeopel 繼承 People
class HappyPeople extends People {
constructor(name, gender, age, mood) {
super(name, gender, age);
this.mood = mood || 'happy';
}
sayHello() {
console.log(`Hi, I am ${this.name}. I am very ${this.mood}.`);
}
}
const summer = new People('Summer', 'Female', '18');
summer.sayHi(); // Hi, I am Summer.
const jimmy = new HappyPeople('Jimmy', 'Male', '20');
jimmy.sayHi(); // Hi, I am Jimmy.
jimmy.sayHello(); // Hi, I am Jimmy. I am very happy.
Module
不管是否在 Module 頂部加上 use strict
,都會使用嚴格模式(Strict Mode)。
import
import { firstName as name } from 'profile.js';
console.log(name); // Nina
export
export const PI = '3.14';
export function getList(category) {
/* ... */
}
推薦閱讀
React - DOM 界的彼方系列。