一、對象冒充
其原理如下:構造函數使用 this 關鍵字給所有屬性和方法指派(即采用類聲明的構造函數方式)。因為構造函數隻是一個函數,是以可使 parent 構造函數 成為 children 的方法,然後調用它。children 就會收到 parent 的構造函數中定義的屬性和方法。例如,用下面的方式定義 parent 和 children:
原理:就是把 parent 構造函數放到 children 構造函數裡面執行一次。那為什麼不直接執行,非要轉個彎把 parent 指派給 children 的 method 屬性再執行呢? 這跟 this 的指向有關,在函數内 this 是指向 window 的。當将 parent 指派給 children 的 method 時, this 就指向了 children 類的執行個體。
二、原型鍊繼承
衆所周知,javascript 是一門基于原型的語言,在 javascript 中 prototype 對象的任何屬性和方法都被傳遞給那個類的所有執行個體。原型鍊利用這種功能來實作繼承機制:
注意:調用 parent 的構造函數,沒有給它傳遞參數。這在原型鍊中是标準做法。要確定構造函數沒有任何參數。
三、使用 call 或 applay 方法
這個方法是與對象冒充方法最相似的方法,因為它也是通過改變了 this 的指向而實作繼承:
apply 方法本人就不舉列了,它和 call 方法的差別在于它的第二個參數必須是數組。
四、混合方式
對象冒充的主要問題是必須使用構造函數方式,這不是最好的選擇。不過如果使用原型鍊,就無法使用帶參數的構造函數了。如何選擇呢?答案很簡單,兩者都用。 在 javascript 中建立類的最好方式是用構造函數定義屬性,用原型定義方法。這種方式同樣适用于繼承機制:
五、使用 object.create 方法
object.create 方法會使用指定的原型對象及其屬性去建立一個新的對象:
@ 當執行 children.prototype = object.create(parent.prototype) 這個語句後,children 的 constructor 就被改變為 parent ,是以需要将 children.prototype.constructor 重 新指定為 children 自身。
六、extends 關鍵字實作繼承
這個是 es6 的文法糖,下面看下es6實作繼承的方法:
上面代碼中,子類的constructor方法沒有調用super之前,就使用this關鍵字,結果報錯,而放在super方法之後就是正确的。子類children的構造函數之中的super(),代表調用父類parent的構造函數。這是必須的,否則 javascript 引擎會報錯。
注意,super雖然代表了父類parent的構造函數,但是傳回的是子類children的執行個體,即super内部的this指的是children,是以super()在這裡相當于parent.prototype.constructor.call(this)。