--- 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. ```