2012-02-13 17 views
33

Böyle bir örneğim var.Neden kurucu işlevini prototipten değiştirmek imkansız?

function Rabbit() { 
    var jumps = "yes"; 
}; 
var rabbit = new Rabbit(); 
alert(rabbit.jumps);     // undefined 
alert(Rabbit.prototype.constructor); // outputs exactly the code of the function Rabbit(); 

Ben var jumps kamu hale gelir, böylece Rabbit() kodu değiştirmek istiyorum. Ben şu şekilde yaparım:

Rabbit.prototype.constructor = function Rabbit() { 
    this.jumps = "no"; 
}; 
alert(Rabbit.prototype.constructor); // again outputs the code of function Rabbit() and with new this.jumps = "no"; 
var rabbit2 = new Rabbit();    // create new object with new constructor 
alert(rabbit2.jumps);     // but still outputs undefined 

Bu şekilde yapıcı işlevindeki kodu neden değiştirmek mümkün değil?

+0

Sizin ikinci kod yanlış, dolayısıyla hata değerlendirdiği, bir Tavşan atlamak yok diyor - 'this.jumps = "evet"' – wheresrhys

+0

@wheresrhys denemek olmayan tüm boş dizeler (daha uzunluğunda yani dizeleri sıfırdan) JavaScript'te doğru olarak değerlendirmek; Hatta "yanlış", daha çok, sonra, "hayır" ':) – Max

cevap

56

'sınıf' kullanıcıları örneğinden yapıcı tespit böylece Rabbit.prototype.constructor, orijinal yapıcısı (function Rabit(){...}) için sadece bir işaretçi olmasıdır:

İşte benim jsfiddle bu. Bu nedenle, ne zaman Az önce orijinal yapıcı ve prototip üzerinde kendisine atfen arasındaki bağlantıyı kırıyorsun

Rabbit.prototype.constructor = function Rabbit() { 
    this.jumps = "no"; 
}; 

yapmaya çalışıyoruz.

function extend(base, sub) { 

    function surrogateCtor() {} 
    // Copy the prototype from the base to setup inheritance 
    surrogateCtor.prototype = base.prototype; 
    // Tricky huh? 
    sub.prototype = new surrogateCtor(); 
    // The constructor property is set wrong (to the base constructor) 
    // with the above trick, let's fix it 
    sub.prototype.constructor = sub; 
} 

Bunu görebilirsiniz: Yani cevap, hayır,

çok kütüphanede aşağıdaki gibi bir şeyle mirası uygulamak JS prototype.constructor

Kalıtım için yeniden atama yoluyla bir kurucu değiştiremezsiniz edilir Yukarıdaki kodda, düzeltmesi yapıcı özelliğine sahibiz, ancak gerçek kurucuyu etkilemez. JS miras hakkında benim yazı Bkz http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

bir kurucu yeniden tanımlamak için nasıl Eğer gerçekten bir yapıcı yeniden tanımlamak istiyorsanız, sadece bunu

var oldProto = Rabbit.prototype; 
Rabbit = function() {...}; 
Rabbit.prototype = oldProto; 
+2

Evet, 'prototype.constructor' gerçekten hiçbir şeyi etkilemiyor. – katspaugh

+1

+1 harika cevap. – Jivings

0

aşağıdaki

function Rabbit() { 
    this.jumps = "no"; 
}; 

var rabbit = new Rabbit(); 
alert(rabbit.jumps); // Prints "no" 
+2

Bu cevabı bir '+ 1' veririm, eğer prototipte 'atlamalar' ayarının çalışmadığını açıklarsanız. –

+0

Evet, teşekkürler, orijinal işlevi değiştirebileceğimi biliyorum. Ama bilmek istiyorum, prototipten başka bir şekilde değiştirmek mümkün. – Green

1

bu deneyin deneyin:

Rabbit.prototype = new function(){ 
    this.jumps = "no"; 
}; 

var rabbit2 = new Rabbit();    // create new object with new constructor 
alert(rabbit2.jumps); 

yerine yapıcı ayar Nesne oluşturulduğunda böylece, yeni bir fonksiyon olması için prototip Nesne ayarlamak istediğiniz prototip, this.jumps değerini hayır olarak ayarlayarak, önceki kurucu tarafından ayarlanan değeri geçersiz kılar. neler oluyor http://jsfiddle.net/ZtNSV/9/

+1

Bu aslında işe yaramaz - prototipin kendisinde atlamalar koymaya eşdeğerdir. Bunu zaten ''Rabbit.prototype = {atlar:' hayır '};' 'diyerek yapabilirsiniz. Ama bunu gerçekten yapmak istemezsiniz çünkü bu prototip, yapıcı işlevindeki herhangi bir şey tarafından geçersiz kılınacaktır. – danShumway

0

, bir hazır değil bir nesne oluşturarak Bu harika geçici çözüm yapıcı işlevinden. Eğer jumps üye yerine yapıcı içinde sadece yerel değişken olmaktan çok, nesnenin içerdiği istiyorsanız

Öncelikle, o zaman this anahtar kelime gerekir.

function Rabbit() { 
    this.jumps = "yes"; 
}; 

var rabbit = new Rabbit(); 
alert(rabbit.jumps);     // not undefined anymore 

Ve şimdi kolayca şimdi istediğin alenen yol jumps erişebilir:

rabbit.jumps = 'no'; 
alert(rabbit.jumps);     // outputs 'no' 

Ama hala başka Tavşan nesnesi oluşturursanız başlangıçta 'evet' yapıcı tanımlanan olacak doğru ?

var rabbit2 = new Rabbit(); 
alert(rabbit.jumps);      // outputs 'no' from before 
alert(rabbit2.jumps);     // outputs 'yes' 

Yapabilecekleriniz, bazı varsayılan Tavşan Nesnelerinden bir Tavşan oluşturmaktır. Beton tavşanları, beton tavşan nesnesindeki değeri (uygulama) değiştirmedikçe, uçarken değiştirseniz bile, varsayılan Tavşan nesnesinin varsayılan değerine her zaman sahip olacaktır. Bu, muhtemelen en iyisi olan ama başka bir bakış açısını açabilen @Juan Mendes'in çözümünden farklıdır.

Rabbit = {jumps : 'yes'}; // default object 

rabbit = Object.create(Rabbit); 
Rabbit.jumps = 'no'; 
rabbit2 = Object.create(Rabbit); 

console.log(rabbit.jumps); // outputs "no" - from default object 
console.log(rabbit2.jumps); // outputs "no" - from default object 

// but... 
rabbit.jumps = 'yes'; 
Rabbit.jumps = 'unknown'; 

console.log(rabbit.jumps); // outputs "yes" - from concrete object 
console.log(rabbit2.jumps); // outputs "unknown" - from default object 
İlgili konular