2014-10-05 32 views
0

假設我有一個javascript類Library1.B,它從同一個庫中的超類繼承methodA
假設我想將Library1克隆到Library2中,以便製作我自己的版本,並稍微覆蓋Library1.B的繼承的methodA以改進它。天真,我闡述了這樣做:Javascript - 在克隆庫中重寫繼承的方法

/* Library 1 */ 
var Library1 = {}; 

Library1.A = function() { 
    console.log("A's constructor called"); 
}; 
Library1.A.prototype.methodA = function() { 
    console.log("methodA called with arguments", arguments); 
    //heavy computation 
}; 

Library1.B = function() { 
    Library1.A.call(this); 
    //Set a few other properties exclusive to B 
}; 
Library1.B.prototype = Object.create(Library1.A.prototype); 

/* Library 2 */ 
var Library2 = Library1; 

Library2.B.prototype.methodA = function() { 
    console.log("Before invoking methodA()"); 
    Library1.B.methodA.apply(this, arguments); 
    console.log("After invoking methodA()"); 
}; 

var o1 = new Library1.B(); 
o1.methodA(1, 2, 3); 

var o2 = new Library2.B(); 
o2.methodA(4, 5, 6); 

(的jsfiddle here

預計日誌上面:

A's constructor called
methodA called with arguments [1, 2, 3]
A's constructor called
Before invoking methodA()
methodA called with arguments [4, 5, 6]
After invoking methodA()

相反,我得到這樣的:

A's constructor called
Before invoking methodA()
Uncaught TypeError: Cannot read property 'apply' of undefined

因此很明顯, o1,儘管是用構建的對象0的構造函數(它又調用Library1.A的構造函數),已經使用Library2的覆蓋的methodA;它然後在Library1.B.methodA.apply電話崩潰,我想因爲Library1.B沒有它自己的methodA,而是從Library1.A繼承。
我的意思是,當我寫Library1.B.methodA實際上是「擡頭Library1.B的原型鏈,直到找到定義methodA,然後調用它this這些arguments」是什麼。
什麼是實現這一目標的正確方法?

+1

你認爲這行做了什麼'var Library2 = Library1'? – elclanrs 2014-10-05 12:23:08

+0

我看到你在哪裏:我期望'Library2'成爲'Library1'的一個*拷貝*,但我想它只是成爲對'Library1'的引用,所以在'Library2'上調用的任何東西實際上都會被調用' Library1'?我會嘗試編輯小提琴,看看問題是否仍然存在,謝謝你的提高。 – 2014-10-05 12:49:43

+0

好吧,編輯jsFiddle(http://jsfiddle.net/axedre/puposqs5/1/),但仍然沒有骰子:與以前一樣的錯誤。 :( – 2014-10-05 12:57:38

回答

1

我編輯你的小提琴是這樣的:

/* Library2 */ 
var Library2={}; 

Library2.B = function() { 
    console.log("L2.B's constructor starts") 
    Library1.B.call(this) 
    console.log("L2.B's constructor ends") 
} 

Library2.B.prototype.methodA = function() { 
    console.log("Before invoking methodA()"); 
    Library1.B.prototype.methodA.apply(this, arguments); //ADDED "prototype" 
    console.log("After invoking methodA()"); 
}; 

現在Library2無關1,我們寫這是從無到有的成員。另一個區別在於你對methodA的超級調用:你正在尋找L1.B中的方法,該方法是一個構造函數,其下的proto是Function。該構造函數的原型儘管(與原底下的不同)是一個空的對象,其底下是構造函數L1.A的原型,它是方法A所在的地方。所以申請代表團沒有任何問題。你只是看着構造函數而不是原始鏈下的任何對象。

現在有什麼比這更簡單的? :^ @

+0

謝謝!會'Library1.B.prototype。即使'methodA'不在'B'的直接超類中(即:如果它必須上升n個層次'B - > A - >,methodA'也會向上運行'Library1.B'的原型鏈。 .. - > X',其中'X'具有'methodA')? – 2014-10-06 11:25:21

+1

那麼這已經是整個鏈條。 Library1.B.prototype的under-proto是Library1.A.prototype,我認爲它的under-proto是一個空對象。你可以打印出來並檢查。但是,否則,是的,它一直在鏈條上工作。 – 2014-10-06 11:34:54

+0

好的,謎底:[this](http://jsfiddle.net/axedre/puposqs5/4/)代碼有什麼問題?這些都在評論中解釋過,如果需要,我會發出一個新問題,但我沒有找到我可以給它的標題的線索 – 2014-10-06 20:44:29