ES6 Class

函式建構式

javascript沒有原生的class,是透過「原型」來繼承方法。透過函式建構式的方式,透過 new 關鍵字來產生新的物件。

1
2
3
4
5
function Person(name) {
this.name = name;
}

let lucy = new Person('lucy');

但由於這種寫法與其他物件導向的程式語言差異太大,所以從ES6開始導入了Class語法。

Class語法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person {
constructor(name) {
this.name = name;
};

greeting() {
return `Hello this is ${this.name}`;
};

const lucy = new Person('lucy');
console.log(lucy.greeting()) // Hello this is lucy
}

首先在class關鍵字後是class的名稱,內部的 constructor函式與原本的 建構函式 function Person(name) {} 是一樣的,greeting方法則直接寫入class裡。

Class與 constructor function的差異

  1. 函式可以被提升,而class不會,會出現「TDZ」暫時性死區
  2. 直接呼叫class名稱,而不是透過 new關鍵字來呼叫,會出現錯誤。
  3. class的區塊內所有程式碼,預設會進入嚴格模式。

getter 與 setter

在 Class 在取屬性值或設定屬性值時,可以直接這樣做:

1
2
3
4
5
6
7
8
9
10

class Pizza {
constructor(pizzaType) {
this.type = pizzaType;
};
}

const myPizza = new Pizza('tomato');
myPizza.type = 'supreme'; // 直接設定新的值
console.log(myPizza.type);

但如果有比較複雜的運用時,可以使用 Getter 和 Setter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

class Pizza {
constructor(pizzaType) {
this.type = pizzaType;
};

get pizzaType() {
return this.type;
}

set pizzaType(pizzaType) {
this.type = pizzaType;
}

const myPizza = new Pizza('tomato');
myPizza.pizzaType = 'sausage'; // 透過 setter 來設定值
console.log(myPizza.pizzaType); // 透過 getter 來取得值
}

getter 與 setter 的寫法也可以簡化成一個函式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Pizza {
constructor(pizzaType) {
this.type = pizzaType;
};

getPizzaType() {
return this.type;
}

setPizzaType(pizzaType) {
this.type = pizzaType;
}
}

const myPizza = new Pizza('tomato');
myPizza.setPizzaType('sausage');
myPizza.getPizzaType();

class 的靜態方法

class 裡面可以宣告靜態方法 (static method),其效果等同於直接定義一個方法在class的屬性上,不用new出新物件就可調用方法:

1
2
3
4
5
6
7
class Article {
static compare(a, b) {
return a.date < b.date ? -1 : 1;
}
}

articles.sort(Article.compare);

extends 繼承類別

class可以用extends語法繼承。例如,想要 Rabbit class繼承自 Animal class。非常簡單,只要使用 class Rabbit extends Animal 語法:

1
2
3
4
5
6
7
8
9
10
11
class Animal {
// ...
run() {
// Run...
}
}
class Rabbit extends Animal {
// ...
}
let rabbit = new Rabbit();
rabbit.run(); // From `Animal`

super 覆寫方法

就像其他語言一樣,繼承的類別可以覆寫母類別的方法,但是通常我們不一定想要整個覆蓋掉母類別的方法,而是會根據既有的母類別的方法去延伸功能。想要延伸既有的方法,可以用 super 關鍵字,呼叫母類別的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal {
// ...
run() {
console.log('Animal run!');
}
}

class Rabbit extends Animal {
// ...
run() {
super.run(); // Animal run!
console.log('Rabbit jump!');
}
}

super 覆寫 constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal {
constructor(name) {
this.name = name;
}
}

class Rabbit extends Animal {
constructor(name, earLength) {
super(name);
this.earLength = earLength;
}
}

let rabbit = new Rabbit('John', 5);

利用 super 關鍵字,在constructor內,呼叫母類別的 constructor。因為母類別已經有 this.name = name; 的邏輯了,不需要在子類別重寫一次 this.name = name ,直接呼叫 super(name); 就可以了。