ES6 淺談class繼承機制

文章來源阮一峰ES6入門,這里做要點掌握大綱。
class——構(gòu)造函數(shù)的語法糖
ES5的繼承:修改原型鏈
先創(chuàng)造子類的實例對象,再將父類的方法添加到this(Parent.apply(this) )

ES6的繼承:通過extends實現(xiàn)繼承
先將父類實例 的屬性方法加到this上(super),然后再用子類的構(gòu)造函數(shù)修改this

  • super
  1. 子類必須在構(gòu)造函數(shù)中調(diào)用super方法,用來創(chuàng)建父類的this對象。因為子類this通過父類構(gòu)造函數(shù)塑造,得到和父類一樣的實例屬性和方法(實例屬性和類的本身屬性參考上一節(jié)class的基本語法。)不調(diào)用super,子類就得不到this。
    在子類的構(gòu)造函數(shù)中,只有調(diào)用super之后才可以使用this 關(guān)鍵字,因為super 之后子類才有了自己的this。
  2. super關(guān)鍵字可以當函數(shù)使用也可以當對象使用。用法不同。必須顯示指定super的數(shù)據(jù)類型
class A {}

class B extends A {
  constructor() {
    super();
    console.log(super.valueOf() instanceof B); // true,valueOf()返回該對象的原始值。
  }
}

let b = new B();

作為函數(shù)使用時,代表父類的構(gòu)造函數(shù),只能在子類構(gòu)造函數(shù)中使用,super內(nèi)部的this指向子類實例。

class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B

作為對象使用時,在靜態(tài)方法中指向父類,在普通方法中,指向父類原型對象。
注意:super指向父類的原型對象,而不是父類實例,所以父類實例上的屬性方法無法通過super調(diào)用。(父類構(gòu)造函數(shù)里this調(diào)用的屬性方法就是實例屬性方法)

class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p;
  }
}

let b = new B();
b.m // undefined

定義在父類實例上的屬性應(yīng)該是這樣子

class A {}
A.prototype.x = 2;

class B extends A {
  constructor() {
    super();
    console.log(super.x) // 2
  }
}

let b = new B();

在普通方法中使用super 對象時, 方法內(nèi)部的this指向當前的子類實例

class A {
  constructor() {
    this.x = 1;
  }
  print() {
    console.log(this.x);
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
  }
  m() {
    super.print();
  }
}

let b = new B();
b.m() // 2

對象總是繼承自另一個對象,所以可以在任意一個對象里使用super

var obj = {
  toString() {
    return "MyObject: " + super.toString();
  }
};

obj.toString(); // MyObject: [object Object]
  • 子類的構(gòu)造方法如果沒有寫也會被自動添加。
  • 子類的實例也是父類的實例
let cp = new ColorPoint(25, 8, 'green');

cp instanceof ColorPoint // true
cp instanceof Point // true
  • 父類的static 方法會被子類繼承
    去class基本語法里會看到靜態(tài)方法(屬性)和私有方法(屬性)的使用方法
    靜態(tài)方法只能直接通過類調(diào)用,但不能被實例繼承,變量名:static variable
    私有方法只能在類內(nèi)部使用 ,變量名:#variable
  • 判斷一個類是否繼承了另一個類
    Object.getPrototypeOf()可以獲取子類的父類
Object.getPrototypeOf(child) === parent
// true
  • 類的prototype屬性和proto屬性
    大多數(shù)瀏覽器的 ES5 實現(xiàn)之中,每一個對象都有proto屬性,指向?qū)?yīng)的構(gòu)造函數(shù)的prototype屬性。Class 作為構(gòu)造函數(shù)的語法糖,同時有prototype屬性和proto屬性,因此同時存在兩條繼承鏈。

(1)子類的proto屬性,表示構(gòu)造函數(shù)的繼承,總是指向父類。

(2)子類prototype屬性的proto屬性,表示方法的繼承,總是指向父類的prototype屬性。
我知道這張圖可能不準確,但是這樣記能讓我一下子找到對應(yīng)關(guān)系。

image.png

  • 子類原型的原型是父類的原型,emm
var p1 = new Point(2, 3);
var p2 = new ColorPoint(2, 3, 'red');

p2.__proto__ === p1.__proto__ // false
p2.__proto__.__proto__ === p1.__proto__ // true

image.png

這里有個作用就是通過子類的實例可以修改父類的實例
子類實例.proto.proto.attr = whatever;,修改父類,進而音箱父類的實例。

  • 原生構(gòu)造函數(shù)的繼承
    原生構(gòu)造函數(shù),是指語言內(nèi)置的構(gòu)造函數(shù),用來生成數(shù)據(jù)結(jié)構(gòu),ES的構(gòu)造函數(shù)有9種:
    Boolean(),String(),Number(),
    Object(),Array(),Function(),
    Date(),RegExp(),Error(),
    后面的我就不想寫了...
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,144評論 2 9
  • class的基本用法 概述 JavaScript語言的傳統(tǒng)方法是通過構(gòu)造函數(shù),定義并生成新對象。下面是一個例子: ...
    呼呼哥閱讀 4,205評論 3 11
  • 簡介 Class可以通過extends關(guān)鍵字實現(xiàn)繼承。 上面代碼定義了一個ColorPoint類,該類通過exte...
    oWSQo閱讀 757評論 0 1
  • 基本語法 簡介 JavaScript語言中,生成實例對象的傳統(tǒng)方法是通過構(gòu)造函數(shù). ES6提供更接近傳統(tǒng)語言的寫法...
    JarvanZ閱讀 941評論 0 0
  • 簡介 Class 可以通過extends關(guān)鍵字實現(xiàn)繼承,這比 ES5 的通過修改原型鏈實現(xiàn)繼承,要清晰和方便很多。...
    emmet7life閱讀 403評論 0 0

友情鏈接更多精彩內(nèi)容