class是es6引入的最重要特性之一。在沒有class之前,我們只能通過原型鏈來模擬類。
基本用法
如果你用過java這樣的純面向對象語言,那么你會對class的語法非常熟悉。
class People { constructor(name) { //構造函數 this.name = name; } sayName() { console.log(this.name); } }
上面定義了一個People類,他有一個屬性 name 和一個方法 sayName(),還有一個構造函數;
你可以這樣使用這個類:
var p = new People("Tom"); p.sayName();
就像函數有函數聲明和函數表達式兩種定義方式,類也可以通過類表達式來定義:
let People = class { constructor(name) { //構造函數 this.name = name; } sayName() { console.log(this.name); } }
你可能以為類聲明和類表達式的區別在於變量提升的不同。但是事實是無論是類聲明還是類表達式的方式來定義,都不會有變量提升。所以下面的寫法是錯的:
var p = new People("Tom"); //錯誤,People 未定義 class People { //... };
類中的所有方法默認都是 strict mode
,所以不用再次聲明了。
繼承
通過關鍵字 extends
來繼承一個類,並且,可以通過 super
關鍵字來引用父類。
class People { constructor(name) { //構造函數 this.name = name; } sayName() { console.log(this.name); } } class Student extends People { constructor(name, grade) { //構造函數 super(name); //調用父類構造函數 this.grade = grade; } sayGrade() { console.log(this.grade); } }
上面的例子中我們定義了一個 Student ,他是 People 的子類。
注意我們在 constructor 中是如何通過 super
調用父類的構造函數的。
getters & setters
現在我們可以通過 get
和 set
關鍵字來定義 getters 和 setters 了。
下面我們給 name
屬性定義 getter 和 setter
class People { constructor(name) { //構造函數 this.name = name; } get name() { return this._name.toUpperCase(); } set name(name) { this._name = name; } sayName() { console.log(this.name); } } var p = new People("tom"); console.log(p.name); //TOM console.log(p._name); //tom p.sayName(); //TOM
仔細看上面的例子,搞清楚最后三行分別會輸出什么,就明白getter 和 setter該怎么用了。
主要是要區分 this._name 和 this.name 的區別。因為我們定義了 name
的讀寫器,而沒有定義 _name
的讀寫器,所以訪問這兩個屬性的結果是不同的。
但是要注意一點,不要這樣寫:
set name(name) { this.name = name; }
因為給 this.name
賦值的時候會調用 set name
,這樣會導致無限遞歸直到棧溢出。
靜態方法
通過 static
關鍵字定義靜態方法:
class People { constructor(name) { //構造函數 this.name = name; } sayName() { console.log(this.name); } static formatName(name) { return name[0].toUpperCase() + name.sustr(1).toLowerCase(); } } console.log(People.formatName("tom"));
靜態方法一般用來提供一些工具方法。
私有屬性
很不幸的時ES6並沒有提供對私有屬性的語法支持,但是我們可以通過閉包來實現私有屬性。
var People = (function() { var p = new WeakMap(); class People { constructor(name) { //構造函數 var privateProperties = { name: name }; p.set(this, privateProperties); } sayName() { console.log(this.name); } get name() { return p.get(this).name; } } return People; })(); var p = new People("tom"); console.log(p.name); p.sayName(); var p2 = new People("bob"); console.log(p2.name); p2.sayName();