ES6與ES5繼承的解析

隨風丶逆風發表於2020-11-20

如果對JS繼承還不甚瞭解,可以閱讀一下《前端學習系列——(十)JavaScript的繼承》

我們先構造好父類:

function Super() {
	this.name = '隨風丶逆風'
}

寄生組合繼承

ES5繼承方式中,普遍認為寄生組合繼承最優,這裡就以它為例:

function Sub1() {
	Super.call(this)
}
// 用於解決組合繼承導致父類屬性被兩次例項化的問題。即子類一份屬性,子類原型上又有一份
Sub1.prototype = Object.create(Super.prototype)
// 修正Sub原型物件上[[Constructor]]指標,從Super指向Sub,方便使用contructor判斷建構函式
Sub1.prototype.constructor = Sub1

ES6繼承

ES6新增了class語法糖,使用extends關鍵詞進行繼承。

值得注意的是,extends關鍵字可以繼承任意具有[[Construct]]和prototype的物件,這是為了向後相容,繼承普通的建構函式。

class Sub2 extends Super {}

兩者的相同點

  1. 子類繼承了父類的例項屬性和方法
const sub1 = new Sub1()
const sub2 = new Sub2()

sub1.hasOwnProperty('name') // true
sub2.hasOwnProperty('name') // true 

在這裡插入圖片描述

  1. 子類繼承了父類的原型屬性和方法,即子類的原型物件的[[Prototype]]指標指向父類的原型物件(原型鏈)
Sub1.prototype.__proto__ === Super.prototype // true
Sub2.prototype.__proto__ === Super.prototype //true

在這裡插入圖片描述

兩者的不同點

都知道class是語法糖,雖然本質上還是原型繼承那一套,但是從語法規範以及實現上而言,還是有些微差別。

ES6靜態屬性和方法的繼承

ES6存在兩條“繼承鏈”:

  • 其一,例項和原型的屬性及方法的繼承與ES5基本一致;
  • 其二,建構函式繼承,在JS中萬物皆是物件,建構函式本身也是個物件,它的[[Prototype]]指標原本是指向Function.prototype,ES6為繼承父類的靜態屬性和方法,將子類的[[Prototype]]指標直接指向了父類,這樣就通過原型鏈訪問到了父類的靜態屬性和方法。
Super.static = 'static'

Sub1.static // undefined
Sub2.static // 'static'
Sub1.__proto__ === Super // false
Sub2.__proto__ === Super // true
Sub1.hasOwnProperty('static') // false
Sub2.hasOwnProperty('static') // false

在這裡插入圖片描述

super關鍵字

  • ES5是先構造子類的this,然後將父類的例項屬性通過call或者bind繫結到子類this上;
  • ES6子類是先構造父類this,然後在this上新增屬性和方法,所以子類必須在constructor()中顯式呼叫super()才能使用this,因為子類並不存在this

相關文章