2014-07-22 81 views
1

爲了更好的結構我嘗試繼承我的類在Javascript中。也許我的方法是完全錯誤或不可行的。這是我的示例代碼:基本的JavaScript繼承問題

function myMotherClass(value){ 
    this.MyValue = value 
} 

function myChildClass(value){ 
    this.prototype = new myMotherClass(value); 
    this.alert = function(){ 
     alert(value); 
    }; 
} 

//myChildClass.prototype = new myMotherClass(1) 

var myClass = new myChildClass(2); 
myClass.alert(); 

here is my fiddle

正如你可以在我的小提琴看到的,如果你使用註釋行它工作正常。

如果你可以看到小提琴,我試圖給myChildClass的cunstructor值到基礎「myMotherClass」。但是,正如你所看到的,有一個未定義的輸出。

感謝您的時間和事先的幫助。

+0

通常OP所發佈的例子的類型是通過使用''constructor''和''''prototype''來實現的請參考[JavaScript中的古典繼承](http://www.crockford.com/javascript /inheritance.html)。 – sarbbottam

+0

請參閱[在函數構造函數中設置原型](http:// stackoverflow。com/questions/16582608/setting-prototypes-inside-function-constructor)幾乎重複的討論。 –

+0

@sarbbottam:除了在那篇文章中,Crockford在創建子構造器的原型時調用父構造器是一個經典的錯誤,這是一種反模式,甚至不能在他的例子中正常工作('Parenizor'預計接收一個'value'參數,但是'ZParenizor.inherits(Parenizor);'調用'Parenizor''沒有'[在inherits'內]]。 –

回答

3

它似乎與註釋掉的行一起工作的原因是該註釋行中的myChildClass函數;但在myChildClass構造函數中的行中,this不是函數,它是由new運算符創建的實例。功能上的prototype屬性是由new運算符將其創建的新實例指定爲其基礎原型的對象; 實例上的prototype屬性沒有特別的含義(例如,它不是指實例的基礎原型)。

正確的方式做,這是這樣的:

// Parent constructor 
function myMotherClass(value){ 
    this.MyValue = value 
} 

// Child constructor 
function myChildClass(value){ 
    // Chain to parent constructor, passing any necessary args 
    myMotherClass.call(this, value); 

    // Other child stuff -- see note below 
    this.alert = function(){ 
     alert(value); 
    }; 
} 

// Set up inheritance by creating myChildClass's prototype 
// property to be an object that is baked by myMotherClass's 
// prototype object; do NOT *call* myMotherClass here, it's 
// a common anti-pattern you'll see in a lot of examples 
inherit(myMotherClass, myChildClass); 

// Create an instance  
var myClass = new myChildClass(2); 
myClass.alert(); 

...其中inherit是:

function inherit(parent, child) { 
    var temp; 

    if (Object.create) { 
     child.prototype = Object.create(parent.prototype); 
    } else { 
     temp = function() { }; 
     temp.prototype = parent.prototype; 
     child.prototype = new temp(); 
    } 
    child.prototype.constructor = child; 
} 

注意與你定義alert的方式,出現這種略顯怪異的行爲:

var o = new myChildClass(42); 
console.log(o.MyValue); // 42 
o.alert();    // alerts "42" 
o.MyValue = 67; 
console.log(o.MyValue); // 67 
o.alert();    // alerts "42" <== !!! 

您可以更改如何定義alert所以它使用MyValue這樣的:

this.alert = function() { 
    alert(this.MyValue); 
}; 

...只要你總是把它通過實例。 (更多關於我的博客:神話方法

但是,如果你要做到這一點,你可以把它移到原型 - 把這個inherit調用樹立鏈後:

myChildClass.prototype.alert = function(){ 
    alert(this.MyValue); 
}; 

這裏是所有放在一起:

// Parent constructor 
function myMotherClass(value){ 
    this.MyValue = value 
} 

// Child constructor 
function myChildClass(value){ 
    // Chain to parent constructor, passing any necessary args 
    myMotherClass.call(this, value); 

    // Other child stuff... 
} 

// Set up inheritance by creating myChildClass's prototype 
// property to be an object that is baked by myMotherClass's 
// prototype object; do NOT *call* myMotherClass here 
inherit(myMotherClass, myChildClass); 

// Add stuff to myChildClass's prototype property 
myChildClass.prototype.alert = function(){ 
    alert(this.MyValue); 
}; 

// Create an instance  
var myClass = new myChildClass(2); 
myClass.alert(); 

如果你有興趣在JavaScript中經典的繼承,我有一個方便的輔助腳本,Lineage,這使得上述簡單,增加了一些有用的FEA tures:http://code.google.com/p/lineagejs/

+1

Hej,謝謝你這個大而詳細的答案,我會嘗試你的建議,並儘快將其標記爲答案:-) – Ipad

+1

完美的是,非常感謝你! :-) – Ipad

+1

@Ipad:不客氣。順便說一句,通過編輯錯誤,我留下了一個變量,聲明在'繼承',它從來沒有使用,清理上面。 :-) –