2011-07-30 11 views
10

Czy ktoś może mi wytłumaczyć, jak używać Me.prototype.constructor = Me; i dlaczego jest potrzebny, kiedy ten kod działa i bez niego?Używanie konstruktora prototypów w JS

W obiekcie prototypu kodu tworzony jest obiekt Me, który jest tworzony i zastępowany starym obiektem prototypowym. Dlaczego muszę wskazywać na konstruktor ME w podanym kodzie?

function Me(){ 
    this.name = 'Dejan'; 

} 

function You(){ 
    this.name = 'Ivan'; 
} 

Me.prototype = new You(); 

somebody = new Me(); 

Me.prototype.constructor = Me; // Why? 

Me.prototype.foo = function(){ 
    alert('Proto Me!'); // It always fire up this alert, ether constructor is pointing to Me or not... ! 
} 

You.prototype.foo = function(){ 
    alert('Proto You!'); 
} 

somebody.foo(); 
alert(somebody.name); // Alert 'Dejan' 
+0

Wierzę, że starsze przeglądarki sprawdzają właściwość '.constructor' dla słowa kluczowego" instanceof ". – Raynos

+0

Jest to książka z 2006 roku. –

Odpowiedz

11

To nie jest potrzebne, a to nie jest nawet potrzebny instanceof Wbrew powszechnemu przekonaniu (instanceof wewnętrznie sprawdza łańcuch prototypu i nie trzeba właściwość konstruktora). Zwykle, constructor jest z natury nierefunkcyjną własnością na konstruktorze prototype. W ten sposób dając dowolne obiekty utworzone przez ten konstruktor, nieprzeliczalną właściwość, wskazując na ten konstruktor.

Dobrze jest umieścić go tam, gdzie trzeba, najlepiej nieprzelotowy. Niektóre kodi zakładają istnienie .constructor obiektów.

W kodzie, który wysłałeś, tak, kiedy dziedziczysz w ten sposób, konieczne jest zresetowanie konstruktora (jeśli tego chcesz), ponieważ obiekt, który stworzyłeś jako prototyp dziecka, ma właściwość konstruktora, która wskazuje na błąd konstruktor (jego konstruktor).

W ES5, zrobiłbyś:

Child.prototype = Object.create(Parent.prototype, { 
    constructor: { value: Child, enumerable: false } 
}); 

edit: Również, może warto wspomnieć, kiedy robi dziedziczenia przy użyciu niestandardowego __proto__, to nie jest konieczne, aby przywrócić konstruktora bo __proto__ jedynie określa i prototyp obiektu , co to znaczy, obiekt, na którym będą wykonywane wyszukiwania, gdy własność własna nie istnieje. Nowy prototype zawsze będzie miał właściwość o nazwie constructor.

Więc robi:

var child = function() {}; 
child.prototype.__proto__ = parent.prototype; 

Nie trzeba ustawić konstruktora, ponieważ konstruktor baza child.prototype nieruchomość jest nadal. Jeśli uzyskano do tego dostęp, nie trzeba wykonywać żadnych wyszukiwania łańcuchów prototypów.

+2

Czy jesteś pewien, że IE6 nie sprawdza właściwości 'constructor'? Natomiast 'Object.create' ustawia dla ciebie właściwość' constructor'. Nie musisz tego robić ręcznie – Raynos

+4

Raynos, Nie Nie jestem pewien co do IE6, biorąc pod uwagę, że naprawdę nie dbam o IE6. Ponadto Object.create nie ustawia konstruktora dla ciebie, nie ma pojęcia konstruktora, w rzeczywistości jest to punkt Object.create. Otrzymałbyś tylko właściwość konstruktora równą konstruktorowi nadrzędnemu, co byłoby błędne dla dziedziczenia. Musisz to zmienić. – chjj

+1

twoje prawo moje złe o "konstruktorze". Object.create nie ma pojęcia konstruktora – Raynos

5

Jeśli zamienić linię

Me.prototype.constructor = Me; // Why? 

z

console.log(Me.prototype.constructor); 
Me.prototype.constructor = Me; // Why? 

można zauważyć, że przed ustawieniem go Me.prototype.constructor jest You, ponieważ Me.prototype jest instancją You ze względu na linii

Me.prototype = new You(); 

Tak, linia z th e // Why? komentarz jest konieczny, aby "naprawić" to błędne wrażenie, że dałeś JavaScript, robiąc dziedziczenie w ten sposób.


Zasadniczo problem pojawia się, ponieważ próbujesz użyć prototypowego dziedziczenia do implementacji klasycznego dziedziczenia. Prototypowe dziedziczenie działa na instancjach obiektów i nie ma koncepcji "klas", a nawet "typów", ale JavaScript sprawia, że ​​rzeczy stają się bardziej mylące z całym biznesem new, .constructor i instanceof.

Bardziej prototypal sposób prowadzenia tego rodzaju rzeczą jest, aby unikać konstruktorów na rzecz konstruktorów elektrowni, czyli funkcji, które zwracają obiekt o formie chec:

function begetPart(partNumber, description) { 
    return Object.create({}, { 
     number: { value: partNumber }, 
     description: { value: description }, 
     describe: { 
      value: function() { 
       alert(this.description); 
      } 
     } 
    }); 
} 

function begetTire(partNumber, speed) { 
    return Object.create(
     begetPart(partNumber, "A tire"), 
     { 
      speed: { value: speed }, 
      describe: { 
       value: function() { 
        alert(this.description + "; speed = " + this.speed); 
       } 
      } 
     } 
    ); 
} 

var genericPart = begetPart(1234, "A widget"); 
genericPart.describe(); // alerts "A widget" 

var tire = begetTire(4567, "fast"); 
tire.describe(); // alerts "A tire; speed = fast" 

Tutaj używamy Object.create powiedzieć " utwórz instancję obiektu na podstawie tej innej instancji obiektu ". Inną instancją jest nowy, pusty obiekt dla begetPart i nową "instancją części" z niektórymi właściwościami wstępnie wypełnionymi dla begetTire.

To lepiej odzwierciedla działanie JavaScript i prototypowego dziedziczenia, ponieważ w dziedziczeniu prototypowym instancje obiektów dziedziczą z innych instancji obiektów, bez tego całego pomysłu "typy" lub "klasy".

+0

'function Object() {[native code]}' – towry

Powiązane problemy