JavaScript super

admin發表於2018-12-15

super關鍵字是ES2015新增,是一個多面手,不同上下文扮演不同角色。

可以充當的角色分別如下:

(1).父類建構函式。

(2).父類原型物件。

(3).父類。

下面將通過程式碼例項對其所扮演的角色進行詳細分析。

一.父類建構函式:


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

class C extends F{
  constructor() {
    super();
  }
}
let c=new C();
console.log(c.webName)


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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/180825dabhg6ehd9jrf6g0.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).子類C通過extends繼承父類F。

(2).在C的constructor建構函式中呼叫super函式,此時它代表父類的建構函式。

(3).雖然是呼叫的父類的建構函式,但是返回的是子類C的例項。

(4).從列印結果來看,子類成功繼承父類的屬性。

更多關於繼承內容可以參閱如下兩篇文章:

(1).JavaScript extends 繼承一章節。 

(2).JavaScript class 類繼承一章節。

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

class C extends F{
  constructor() {
    this.address="青島市南區";
    super();
  }
}
let c=new C();

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/180949agwzouwtege0pwrp.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

由於對super錯誤使用,導致程式碼報錯,分析如下:

(1).子類建構函式必須要呼叫一次super(),且必須在this使用之前呼叫。

(2).因為子類的this必須要利用父類的建構函式建立,呼叫父類的建構函式,可以獲取父類的例項方法和例項屬性,然後在此基礎上新增自身的屬性和方法,生成自己的this,於是在呼叫super之前,子類是沒有this存在的。

特別說明:

(1).如果子類沒有顯式宣告constructor建構函式,自然也無需呼叫super函式。

(2).作為函式呼叫,必須是在子類的constructor建構函式中使用,否則將會報錯。

二.父類的原型物件:

關於原型的基本用法可以參閱JavaScript prototype 原型一章節。

當在非靜態方法中使用super的時候,它可以作為父類的原型物件。

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

class C extends F{
  constructor() {
    super();
    super.show(); 
  }
}
let c=new C();

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/181045iac22e4c6ze7v6az.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).C繼承父類F。

(2).通過new運算子建立類C的物件例項的時候,會首先呼叫C的constructor建構函式。

(3).super()必須要呼叫,否則會報錯,並且在this使用之前呼叫。

(4).super.show()中的super指代父類的原型物件,所以列印結果是"青島市南區"。

(5).constructor建立的屬性是自有屬性,不屬於原型物件,所以無法列印webName屬性值。

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

class C extends F{
  constructor() {
    super();
    this.webName="百度";
    super.show(); 
  }
}
let c=new C();

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/181119es4zivyexexmsves.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

雖然super指向父類原型物件,但通過它呼叫父類原型物件方法時候,方法this指向子類例項。

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

class C extends F{
  constructor() {
    super();
  }
  func(){
    super.address="青島市南區";
  }
}
let c=new C();
c.func();
console.log(c.hasOwnProperty("address"));
console.log(c.address);

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/181146qkk41rxskjk7sz54.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

雖然super指向父類的原型物件,但是this是指向子類例項物件。

所以可以通過super新增或者修改非原型鏈上的自有屬性。

三.父類:

如果用作物件,且位於靜態方法之中,那麼它指向父類。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
class F {
  static func(msg) {
    console.log("父類靜態方法", msg);
  }

  func(msg) {
    console.log("父類例項方法", msg);
  }
}

class C extends F{
  static func(msg) {
    super.func(msg);
  }

  func(msg) {
    super.func(msg);
  }
}

C.func("螞蟻部落");
let c = new C();
c.func("螞蟻部落");

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/181230loonbo6of6qon858.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).super在靜態方法中用作物件,那麼它指代父類,所以C.func("螞蟻部落")呼叫的是父類的靜態方法,如果靜態方法中存在this,那麼this指向子類,而不是父類。

(2).在普通方法中將super用作物件,那麼它指代父類的原型物件,所以c.func("螞蟻部落")呼叫的是父類原型物件上的func方法,但是方法的this是指向子類物件例項。

四.物件中使用:

前面介紹的super都是在類中使用,其實也可以在物件中使用。

因為物件基本上總會繼承於其他物件(類)。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let obj = {
  show(){
    console.log(super.toString());
  }
}
obj.show();

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

a:3:{s:3:\"pic\";s:43:\"portal/201812/15/181306lz60kw633lksstzv.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

但是上述寫法只能採用ES2015新增的語法方式,如果修改成如下方式會報錯:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let obj = {
  show:function(){
    console.log(super.toString());
  }
}
obj.show();

上述程式碼會報錯,不再演示截圖。

相關文章