ES6 Top Features You Must Know

ES6 Top Features You Must Know

ES6 快速小筆記。

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

原本的寫法

var foo = {
  name: name,
  getName: 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

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 界的彼方系列。


javascript prototype operator 運算子 ES6 javascript ReferenceError undefined