JavaScript是一個以原型為基礎(prototype-based)的物件導向程式語言,而 ES6 Class 只是個語法糖(syntactical sugar),目的是提供更簡潔的語法來作物件建立與繼承。
我們過去使用 function constructor 來產生類別物件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function Employee(name, age,salary) { this.name = name; this.age = age; this.salary = salary; }
Employee.prototype.getName = function() { return this.name; }
Employee.prototype.employeeDetails = function() { return 'Name: '+this.name+', Age:'+this.age+', salary:'+this.salary; }
var felix = new Employee('Felix', 18, 22000);
console.log(felix.employeeDetails());
var hector= new Employee('Hector', 25, 36000);
console.log(hector.employeeDetails());
|
ES6 Constructor
類別宣告(Class Declaration)
一個定義類別的方法是使用類別宣告(class declaration),使用關鍵字 class 搭配類別名稱(此例為 “Employee”)。
1 2 3 4 5 6 7
| class Employee{ constructor(name, age, salary) { this.name= name; this.age = age; this.salary= salary; } }
|
類別敘述(Class Expression)
類別敘述是定義類別的另一種方法,可區分為有名稱或無名稱的類別敘述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var Employee = class { constructor(name, age, salary) { this.name= name; this.age = age; this.salary= salary; } }
var Employee = class Employee{ constructor(name, age, salary) { this.name= name; this.age = age; this.salary= salary; } }
var hector= new Employee('Hector', 25, 36000);
|
Hoisting
函式宣告和類別宣告的一個重要差別在於函式宣告是會 hoisted,而類別宣告則不會。使用類別宣告方法,需要先宣告類別才能進行存取,否則會出現 ReferenceError 的錯誤。
1 2 3 4
| var Vincent = new Employee();
class Employee{}
|
以下為將第一個例子修改為 Class 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Employee{ constructor(name, age, salary) { this.name= name; this.age = age; this.salary= salary; } getName() { return this.name; } employeeDetails() { return 'Name: '+this.name+', Age:'+this.age+', salary:'+this.salary; } }
var felix = new Employee('Felix', 18, 22000); console.log(felix.employeeDetails());
var hector= new Employee('Hector', 25, 36000); console.log(hector.employeeDetails());
|
改由 constructor 定義物件內的屬性,並將以前的 prototype 直接寫在 class 內,讓程式碼更為直觀。
靜態方法
我們可以在 class 內定義靜態方法,靜態方法只能被原型使用,無法在創立的物件上使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Employee{ constructor(name, age, salary) { this.name= name; this.age = age; this.salary= salary; } static testMethod(){ return 'static method has been called.'; } }
var hector= new Employee('Hector', 25, 36000);
hector.testMethod();
Employee.testMethod()
|
Get and Set
get 與 set 關鍵字分別代表取得方法和設定方法,一般的公開的的屬性不需要用到這兩種方法,本來就能直接取值或設定;只有私有屬性才需要用到 get 和 set 方法來作取得或設定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Employee{ constructor(name, age) { this.name= name; this.age = age; }
get salary() { console.log("The code executed on getting obj.salary"); if (this._salary!== undefined) {
return this._salary; } else { return 'no salary prop' } }
set salary(value) { console.log("The code executed on setting obj.salary = value;") this._salary=value; } }
var hector = new Employee('Hector',18);
hector.salary='35000';
hector.salary;
|
getter不會有傳入參數,setter 則只能傳入一個參數。
繼承
我們之前透過函式建構式來達成類別繼承,為了讓子類別繼承父類別建構函式的內容,所以我們必須在子類別建構函式中呼叫父類別建構函式:
1 2 3 4 5 6 7 8 9 10 11 12
| function Person(name,age) { this.name = name || 'default'; this.age = age || 0; this.skill= ['HTML','CSS']; }
function Student(name) { this.name = name; this.score = 100; Person.call(this,name); }
|
extends
ES6 簡化類別宣告的過程,我們不需要再去修改原型物件,也能直接完成繼承的效果。
這裡會使用到兩個關鍵字:
extends
: 繼承於另一個原型之下。
super
: 使用上層的值(屬性)。
創造子類別 Student,並使用 extends 指向 Person,讓 Student 繼承 Person:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Person{ constructor(name, age) { this.name = name || 'default'; this.age = age || 0; this.skill= ['HTML','CSS']; }
hi() { console.log(`Hi, ${this.name} ,My age is ${this.age}.`); } }
class Student extends Person{ constructor(name) { super(name); this.name = name; this.score = 100; }
say() { console.log(`Say, ${this.name} ,My score is ${this.score}.`); } }
var roman = new Student('roman');
|
繼承的子類別中的建構式, super() 需要放在建構式第一行,這是標準的呼叫方式。如果有需要傳入參數可以傳入。
繼承的子類別中的屬性與方法,都會覆蓋掉原有的在父母類別中的同名稱屬性或方法,要區分不同的屬性或方法要用 super 關鍵字來存取父母類別中的屬性或方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Person{ constructor(name, age) { this.name = name || 'default'; this.age = age || 0; this.skill= ['HTML','CSS']; } hi() { console.log(`Hi, ${this.name} ,My age is ${this.age}.`); } }
class Student extends Person{ constructor(name) { super(name); this.name = name; this.score = 100; } hi() { console.log(super.hi()); } }
var roman = new Student('roman');
roman.hi();
|
參考文獻
https://ithelp.ithome.com.tw/articles/10185583
https://ithelp.ithome.com.tw/articles/10195056
https://ithelp.ithome.com.tw/articles/10226111
https://ithelp.ithome.com.tw/articles/10196867