大給後,對於昨天的文章提到的繼承原型方法,不知道大家是否理解了呢?
今天我們要針對那個方法再做一些延伸與調整,我們利用 call 的方式並沒有辦法傳遞參數到父層類別,因為使用 call 沒有帶入傳入的參數,所以我們可以改用 apply 將 arguments 傳入父層類別中。
就讓我們看看下方的程式碼吧!
function A(abc) {
this.abc = abc || 12;
console.log("A Class"); // 繼承時會執行兩次
}
A.prototype.show = function() {
console.log(this.abc);
};
function B() {
A.apply(this, arguments);
}
B.prototype = new A();
var objB = new B(11);
B.prototype.square = function() {
console.log( this.abc * this.abc );
};
objB.square(); 121
另外我準備了這段程式碼的原型鏈圖,讓讀者們可以更好理解其中的相對關係。
這樣我們就做到了傳遞參數到父層類別,但有些人會疑問,為什麼我特別寫了 繼承時會執行兩次 ?
沒錯,上述的做法有一個缺點,就是在會讓父類別的建構函式重複執行了兩次,下一段,我們就要來解決這個問題。
使用暫時類別的繼承方法,不會讓父類別的建構函式執行兩次
。利用暫時類別的 prototype 設定父類別的 prototype,子類別的 prototype 再設定暫時類別產生出來的物件。
子類別 super 方法設定父類別的 prototype,最後重新設定子類別 prototype.constructor 到子類別,否則會造成子類別的 constructor 會變成是父類別的 constructor。
是不是有點繞口?沒關係,現在就讓我們看程式碼吧!
// 在 Function 的 原型上擴充一個叫 inherits 的方法
Function.prototype.inherits = function(superCtor) {
function F() {
};
// 利用暫時類別的 prototype 設定父類別的 prototype
F.prototype = superCtor.prototype;
// 子類別的 prototype 設定成暫時類別產生出來的物件
this.prototype = new F();
// 子類別 super 方法設定父類別的 prototype
this.super = superCtor.prototype;
// 設定子類別 的 prototype.constructor 到子類別
this.prototype.constructor = this;
};
function A(abc) {
this.abc = abc || 12;
console.log("A Class");
};
A.prototype.show = function() {
console.log(this.abc);
};
function B() {
A.apply(this, arguments);
}
B.inherits(A);
var objB = new B(11);
B.prototype.square = function() {
console.log( this.abc * this.abc );
};
objB.square(); // 121
這樣我們就避免了父類別的建構函式重複執行,如果還是不太明白的讀者們,可以看看下方的原型鏈圖哦!
若是讀這段感覺到很吃力的讀者別太緊張,因為 ES6 的語法糖 Class 已經幫我們大大的簡化這部分的程式碼囉,所以可以先懂其中的概念就好。
下週就是國慶連假了,窩豪興奮 RRRR
參考資料:
Tommy - 深入 JavaScript 核心課程