---
tags: ES6, Javascript
disqus: hackmd
---
# [JS]類別(class) - constructor、extends、super、static、Getter & Setter
[JavaScript | ES6 中最容易誤會的語法糖 Class - 基本用法](https://medium.com/enjoy-life-enjoy-coding/javascript-es6-%E4%B8%AD%E6%9C%80%E5%AE%B9%E6%98%93%E8%AA%A4%E6%9C%83%E7%9A%84%E8%AA%9E%E6%B3%95%E7%B3%96-class-%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95-23e4a4a5e8ed)
[super](https://es6.ruanyifeng.com/#docs/class-extends#super-%E5%85%B3%E9%94%AE%E5%AD%97)
---
### constructor
一個類別只能有一個名為建構子(constructor)的特別方法。
constructor方法是類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加。
一個建構子可以用關鍵字 super 來呼叫父類別的建構子。
constructor是默認的方法,即使在宣告class的時候沒有,最後還是會被默認加入。
```javascript=
class Point {}
Point.prototype; //{constructor: ƒ}
```
### extends
繼承類別(extends),使用extends可以繼承另一個類別的屬性(properties)與方法(method)。
```javascript=
class Animal {
// ...
run() {
console.log('Animal run!');
}
}
class Rabbit extends Animal {}
var a = new Rabbit();
a.run(); //Animal run!
```
Rabbit這個類雖然沒有任何的方法可以用,但是透過extends Animal,他也可以使用Animal的run這個方法了。
#### 兩種 extends 幫你自動建立的 [[prototype]] 關聯
使用 extends 語法,會自動建立下列兩種 prototype 的繼承關係:
`Rabbit.prototype.__proto__ === Animal.prototype`
`Rabbit.__proto__ === Animal`
第一個是為了達成一般方法的繼承,第二個是為了達成靜態方法的繼承。
### super
呼叫父類別,是用來提供一個類別呼叫其父類別的函數。
super這個關鍵字,既可以當作函數使用,也可以當作對象使用。在這兩種情況下,它的用法完全不同。
super當作函數使用時必須放在建構子(constructor)裡。
```javascript=
class Person {
constructor(name) {
this.name = name;
}
getFrom() {
const state = 'Taiwan';
return `${this.name} from ${state}.`;
}
run() {
console.log('You Run!');
}
}
// 使用 extends 指定 parent class
class Employee extends Person {
constructor(name, position) {
// 用 super 呼叫 extends 指定的 class
super(name);
this.position = position;
}
getPosition() {
return `${this.name}'s position is a ${this.position}.`;
}
}
const luck = new Employee('Luck', 'Front-end');
console.log(luck.getFrom()); // Luck from Taiwan.
console.log(luck.getPosition()); // Luck's position is the Front-end.
```
繼承後只要子類別沒有要建立屬性(Properties)的時候就可以不用,放constructor跟super。
constructor本來就會預設建立。
super則是因為沒有參數要傳給父類別,所以可以不寫。
super作為對象,可以透過super去使用父類別的方法(Method)。
```javascript=
class Animal {
// ...
run() {
console.log('Animal run!');
}
}
class Rabbit extends Animal {
// ...
run() {
super.run(); // Animal run!
console.log('Rabbit jump!');
}
}
var b = new Rabbit();
b.run(); // Animal run!
// Rabbit jump!
```
### static
在 Class 內的 Method 可以加上 static 前綴,使它變成 Static Method (靜態方法),被定義為 Static Method 可以直接以 Constructor 呼叫,但創建出來的 Instance 是無法使用它的:
```javascript=
class Person {
constructor(name) {
this.name = name;
}
static sayHello(name) {
return `Hi!${name}!`;
}
getFrom() {
const state = 'Taiwan';
return `${this.name} from ${state}.`;
}
}
console.log(Person.sayHello('Luck')); // Hi!Luck!
var a = new Person('apple');
a.getFrom(); //apple from Taiwan.
a.sayHello('aaa'); //a.sayHello is not a function
```
### Getter & Setter
與 ES5 一樣,在“類”的內部可以使用get和set關鍵字,對某個屬性設置存值函數和取值函數,攔截該屬性的存取行為
目前還看不太懂,感覺像是把age這個方法分成了兩個。
```javascript=
class Person {
constructor(name) {
this.name = name;
}
static sayHello(name) {
return `Hi!${name}!`;
}
get age() {
if (this._age !== undefined) {
return `${this.name} age is ${this._age}.`;
}
return `Don't know ${this.name}'s age.`;
}
set age(age) {
this._age = age;
}
getFrom() {
const state = 'Taiwan';
return `${this.name} from ${state}.`;
}
}
const john = new Person('John');
console.log(john.age); // Don't know John's age.
john.age = 18;
console.log(john.age); // John age is 18.
```