ES6中的類只是語法糖,它並沒有改變類實現的本質。

舉個例子,在ES5中定義一個類:

function Person(name) {

this。name = name;

}

Person。prototype。sayHello = function(){

return ‘Hi, I am ’ + this。name;

}

而用ES6的寫法重寫一下,檢測型別發現Person本質上仍然是函式:

class Person {

constructor(name){

this。name = name;

}

sayHello(){

return ‘Hi, I am ’ + this。name;

}

}

typeof Person; //‘function’

呼叫的方式都是一致的:

var me = new Person(‘Yecao’);

用ES6定義class中的方法,定義在原型物件上的。與ES5不同的是,這些定義在原型物件的方法是不可列舉的。

ES6類和模組是嚴格模式下的;

不存在變數提升,保證子類父類的順序;

類的繼承也有新的寫法:

class Female extends Person {

constructor(name){

super(name); //呼叫父類的,呼叫之後,子類才有this

this。gender = ‘female’;

}

sayHello(){

return super。sayHello() + ‘, I am ’ + this。gender;

}

}

注意點,子類必須在父類的建構函式中呼叫super(),這樣才有this物件,因為this物件是從父類繼承下來的。而要在子類中呼叫父類的方法,用super關鍵詞可指代父類。

ES5中類繼承的關係是相反的,先有子類的this,然後用父類的方法應用在this上。

ES6類繼承子類的this是從父類繼承下來的這個特性,使得在ES6中可以構造原生資料結構的子類,這是ES5無法做到的。

ES6也可以定義類的靜態方法和靜態屬性,靜態的意思是這些不會被例項繼承,不需要例項化類,就可以直接拿來用。ES6中class內部只能定義方法,不能定義屬性。在方法名前加上static就表示這個方式是靜態方法,而屬性還是按照ES5的方式來實現。

// ES5寫法

Person。total = 0; //靜態屬性

Person。counter = function(){ //靜態方法

return this。total ++ ;

}

// ES6寫法

class Person {

。。。

static counter(){

return this。total ++ ;

}

}

Person。total = 0;

ES6中當函式用new關鍵詞的時候,增加了new。target屬性來判斷當前呼叫的建構函式。這個有什麼用處呢?可以限制函式的呼叫,比如一定要用new命令來呼叫,或者不能直接被例項化需要呼叫它的子類。

function Person(name){

if(new。target === Person){

this。name = name;

}

else{

throw new Error(‘必須用new生成例項’);

}

}

目前瀏覽器對ES6支援的不好,如果要用ES6寫程式碼,必須使用轉譯工具,比如Babel。

最後上兩張圖,理一下__proto__, prototype, constructor之間的關係。

小記ES5和ES6的類

小記ES5和ES6的類

小記ES5和ES6的類

小記ES5和ES6的類

這兩張圖中其實有一處共同的錯誤,你發現了嗎?

另外,我覺得ES5中的繼承的圖中,父建構函式與子建構函式也是可以有直接的關係的。

參考資料:

ECMAScript 6入門 阮一峰 ES 6標準入門

ES5和ES6中的繼承 - KeenWon | 做有趣的事 ES5和ES6中的繼承