JavaScript class 繼承

admin發表於2018-12-16


JavaScript是一門物件導向的語言,與典型面嚮物件語言的繼承相較有其自身特點。

隨著版本的演化,JavaScript繼承從外觀上看更加趨向於典型物件導向的語言。

但繼承依然是基於prototype原型實現,本文將進行一下總結。

關於class類基本用法可以參閱JavaScript class 類一章節。

一.extends實現繼承:

ES2015新增extends關鍵字,利用它可以實現類之間的繼承。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F{
  constructor(){
    this.webName ="螞蟻部落" ;
  }
  showInfo(){
    console.log(this.webName);
  }
}
class C extends F {
  constructor(){
    super();
    this.address="青島市南區";
  }

}
let c=new C();
c.showInfo();
console.log(c.address);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201812/16/204229ehu6ulmqymqil6ui.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).子類C繼承父類F,那麼父類的屬性和方法將會被子類繼承。

(2).如果子類顯示使用constructor建構函式,那麼必須在其中呼叫super函式,且位於第一次使用this之前。

(3).super在子類constructor中相當於父類的建構函式,呼叫super會獲得父類的例項方法和例項屬性,然後在此基礎上,子類建立自己的this,所以說子類在使用this之前必須要首先呼叫super。

更多內容可以參閱如下兩篇文章:

(1).JavaScript super一章節。

(2).JavaScript extends 繼一章節。

與ES2015之前的繼承方式不同點:

(1).ES5是首先建立子類(建構函式)自身的this(指向物件例項),然後將父類屬性與方法新增到子類例項之上。

(2).ES2015則是在父類例項的基礎上,加工建立自己的this(物件例項)。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F{}
class C extends F {
  constructor(){}
}
let c=new C();

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201812/16/204320v5h50e6ex5e7hx61.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

子類建構函式中,沒有呼叫super,即便沒有this的應用也會報錯。

如果子類沒有顯式使用建構函式則不會報錯,程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F{
  constructor(){this.webName="螞蟻部落"}
}
class C extends F {
}
let c=new C();
console.log(c.webName);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201812/16/204346o266j7j2vz56wlll.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

子類並沒有顯式使用constructor建構函式,也就可以不用呼叫super函式。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F{
  static func() {
    console.log("螞蟻部落");
  }
}
F.address="青島市南區";
class C extends F {
}
C.func();
console.log(C.address);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201812/16/204418an56wst1z5dticiy.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

不但可以繼承例項屬性與例項方法,也可以繼承靜態屬性與靜態方法。

關於靜態屬性與靜態方法參閱JavaScript 靜態屬性與靜態方法一章節。

二.類繼承中的prototype:

ES2015雖然增加了class 類,但它只是一個語法糖。

本質依然是fucntion函式,原有的prototype原型依然有效。

上文已經介紹了,類的可以實現靜態屬性與方法和例項屬性與方法的繼承。

由此我們可以推測,存在兩條繼承鏈,程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F {}
class C extends F {}

console.log(C.__proto__ === F);
console.log(C.prototype.__proto__ === F.prototype);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201812/16/204450lsbruup2d92qeqrj.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).C.__proto__ === F返回true,在此條繼承鏈中,類以物件的身份存在,於是C物件的原型物件是F,那麼C將繼承F上的所有屬性與方法,於是就實現了靜態屬性與靜態方法的繼承。

(2).C.prototype.__proto__ === F.prototype返回true,在此條繼承鏈中,類迴歸身份本身,C的原型物件繼承F原型物件,也就是子類的原型物件會繼承父類的原型物件的屬性與方法。這時問題來了,類建構函式中定義的自由屬性怎麼實現繼承的呢,這些屬性是靠super實現的。

相關閱讀:

(1).super參閱JavaScript super一章節。

(2).__proto__參閱JavaScript __proto__一章節。

(3).prototype參閱JavaScript prototype一章節。

相關文章