2013-08-31 27 views
5

Mam tło Java i ostatnio eksperymentowałem z dziedziczeniem JavaScript. Zacząłem pisać obiekty i po przeczytaniu kilku przykładów znalazłem styl kodu, który najbardziej mi odpowiada.Dlaczego warto używać Object.create do prototypu podczas rozszerzania obiektu?

Oto co mam:

var Class = function() {}; 
Class.extend = function(p_constructor) { 
    var Superclass = this; 
    // the following line confuses me 
    p_constructor.prototype = Object.create(Superclass.prototype); 
    p_constructor.prototype.constructor = p_constructor; 
    p_constructor.extend = Superclass.extend; 
    return p_constructor; 
}; 

Więc teraz, kiedy chcą określić przedmiot, który rozciąga klasy I wpisz:

var Person = Class.extend(function(p_firstName, p_lastName) { 
    this.firstName = p_firstName; 
    this.lastName = p_lastName; 
}); 

i dodaje będzie prawdziwe:

var p = new Person('john', 'smith'); 
p instanceof Person; // true 
p instanceof Class; // true 

Mam tylko problemy ze zrozumieniem, co jest ef fective różnica pomiędzy następującymi liniami w funkcji Class.extend:

/* 1) */ p_constructor.prototype = new Superclass(); 
/* 2) */ p_constructor.prototype = Superclass.prototype; 
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 
/* 4) */ p_constructor.prototype = Object.create(Superclass); 

Zdaję sobie sprawę, że za pomocą 1 linia nie jest bardzo mądry, jeśli niektóre Super konstruktorzy rzucać błędy, ale co to dokładnie jest różnica między liniami 2, 3 i 4?

Odpowiedz

6

Aby odpowiedzieć na moje własne pytanie:

/* 1) */ p_constructor.prototype = new Superclass(); 

Tak jak mówiłem, to nie jest bardzo mądry, aby to wykorzystać, ponieważ faktycznie tworzy cały obiekt nadklasy. Cały punkt prototypowego dziedziczenia polega na współużytkowaniu prototypowych obiektów, dzięki czemu można uniknąć redundantnych definicji funkcji (a czasem obiektów).

/* 2) */ p_constructor.prototype = Superclass.prototype; 

Byłoby OK, gdyby można było mieć pewność, że prototyp konstruktora nigdy nie zostanie zmodyfikowany przez stronę trzecią. Załóżmy, że ktoś, kto używa twojej klasy, chce dodać dodatkową funkcjonalność do swojego prototypu. Zmiana prototypu p_constructor miałaby bezpośredni wpływ na prototyp klasy superklasy i mogłaby wprowadzić błędy w zachowaniu nadklasy. Więc następnym linia kodu jest używany zamiast:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 

ta tworzy nowy obiekt (instancja), którego prototyp (właściwie zmienna __proto__) jest ustawiony na prototypie nadklasy. Wszelkie zmiany w p_constructor.prototype nie wprowadzają teraz żadnych zmian w zachowaniu Superklasy.

/* 4) */ p_constructor.prototype = Object.create(Superclass); 

Górna linia działa, ale nie ma sensu, ponieważ ustawia prototyp tylko dla konstruktora Superklasy.

Również następujący wiersz został mylące dla mnie, a także:

p_constructor.prototype.constructor = p_constructor; 

To sprawia, że ​​nie ma różnicy w zachowaniu p_constructor jest, to tylko sprawia, że ​​odniesienie do konstruktora dostępnego w instancja obiektu. Zgrabny Sztuką jest dodanie superklasę do prototypu, a także:

p_constructor.prototype.superclass = Superclass; 

I wtedy następujący fragment kodu, który działa:

function Constructor(p_params) { 
    // call constructor of the superclass 
    this.superclass(p_params); 
} 
+0

Chłodny, że już odpowiedział na to pytanie tutaj.W swoim ostatnim bloku kodu rozważ kontekst konstruktora klasy superklasy, gdy nazwiesz go w ten sposób; Myślę, że to, co chcesz zrobić, to 'this.superclass.apply (this, arguments); - wtedy, jeśli konstruktor super idzie' this.sumthin = ... ', wartość jest dołączona do instancji podklasy '. – dalgard

+0

Wartości z nadklasy byłyby w każdym razie dołączone do bieżącego wystąpienia podklasy, ponieważ jest wywoływane z 'tego', więc jego kontekst będzie faktycznie tym samym nowym wystąpieniem podklasy. – jeremija

+0

Och, masz rację. Myślę, że widzę ten wzorzec dostępu do super częściej: 'subclass.prototype.super = superclass.prototype' (prawdopodobnie z dodatkiem' subclass.super = superclass'). Być może zainteresowałbyś się tym [moim rozwiązaniem] (https://gist.github.com/dalgard/9169923) na te rzeczy (zobacz przykład w komentarzach). – dalgard

Powiązane problemy