2015-04-26 19 views
5

Jaka jest różnica między tymi dwiema implementacjami prototypowego dziedziczenia i biorąc pod uwagę, że pracujemy z 2 różnymi "prototypami" (prototypowa własność, która dotyczy tylko funkcji i wewnętrznego prototypu), i jak te implementacje różnią się w swoim prototypie wyszukiwanie łańcucha? Czy pierwsza implementacja (przy użyciu właściwości prototypu) opiera się na korzystaniu z operatora new?Jaka jest różnica między tymi dwiema implementacjami prototypowego dziedziczenia?

Przypisanie do prototype własności funkcjonuje 'a za pomocą operatora new:

function foo() {} 

foo.prototype.output = function(){ 
    console.log('inherits from Function.prototype property'); 
}; 

bar = new foo(); 
bar.output(); 

Przechowywanie funkcję w obiekcie dosłownym i stosując metodę Object.create():

var foo = { 
    output: function(){ 
    console.log('inherits from the internal prototype'); 
    } 
}; 

var bar = Object.create(foo); 
bar.output(); 
+0

Jedną z różnic jest to, że 'Object.create' jest nowszy, i nie jest obsługiwana w IE8 i poniżej – keune

+0

nie widzę prototypal dziedziczenie ** ** w swoich przykładach. – hindmost

+0

@ czy najdokładniej możesz to rozwinąć? – shmuli

Odpowiedz

3

Główną różnicą jest w taki sposób, w jaki jest używany i związane z nim niebezpieczeństwa.

Pierwsza z nich zmusza do użycia new, gdy chcesz utworzyć nowy obiekt. Składnia jest dość brzydka (SomeConstructor.prototype.method) i ma jedną poważną wadę: wywołanie konstruktora, który dodaje właściwości (this.name = nameParam ...) bez new zastosuje konstrukcję do obiektu globalnego. Zachowanie konstruktora jest dziwne (utwórz nowy obiekt, który deleguje do SomeConstructor.prototype, następnie zastosuj konstruktor do nowego obiektu, a następnie, jeśli konstruktor zwróci coś, zastąp obiekt czymś). Dodatkowo, w twoim przykładzie, foo sam nie jest użyteczny, musisz utworzyć nowy obiekt, aby uzyskać dostęp do jego funkcjonalności.

Drugi, Object.create, nie wymusza na użytkowniku żadnych syntetycznych dziwactw. Nie masz globalnego ryzyka zanieczyszczenia. Obiekt foo ma funkcjonalności, które mogą być już używane bez tworzenia nowego obiektu, a bar pożyczy te funkcje. Tego rodzaju wzorzec może również ułatwić wdrażanie fabryk (bez możliwości zastąpienia ich wszędzie) i pul obiektów w razie potrzeby.

Eric Eliott talks about it very well i Kyle Simpson wrote a whole book o delegacji prototypowej!

A oto jak odnośnika dzieje:

  • W konstruktorze odnośnika odbywa się na Constructor.prototype (nie rzeczywisty wewnętrzny prototypu konstruktora, ale jego prototype nieruchomość Jeśli okaże się to kłopotliwe. , gratulacje, jesteś człowiekiem). Dodatkowe właściwości ustawia się w funkcji konstruktora. foo sam nie jest używany do wyszukiwania, foo.prototype (ponownie, nie taki sam, jak foo.__proto__, który wskazuje na funkcję) jest używany do tego.
  • Z Object.create wyszukiwanie odbywa się na samym obiekcie (foo). Na obiekcie nie ma nieprototypowej właściwości.

Istnieje very funny diagrams on this page of Kyle Simpson's book, które wyjaśniają to dalej.

Więcej na new w tej kwestii: Is JavaScript's "new" keyword considered harmful?

+1

Tryb ścisły rozwiązuje problem globalnego zanieczyszczenia. – jdphenix

+0

@Kyll co różni się od "wyszukiwania"? Te implementacje używają 2 różnych obiektów "prototypowych", nie? – shmuli

+0

Pozwól mi to edytować! –

-1

Pierwszy przykład - foo, jest funkcją.

Drugi przykład - foo jest obiektem.

w drugim przykładzie pasek staje się nową instancją bez konstruktora. Zobacz - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create, aby dodać konstruktora.

Na marginesie, powszechną najlepszą praktyką, że konstruktorzy powinni zaczynać się od dużej litery.

1

OK, przede wszystkim w przypadku, gdy nie wiadomo, Object.create opiera się na następującym wzorem zaproponowanym przez Douglasa Crockforda (czytaj więcej here):

function create (proto) { 
    function f() {} 
    f.prototype = proto; 
    return new f(); 
} 

Teraz trzeba mieć świadomość, że powyższy kod nie daje tego samego wyniku, jeśli parametr null zostanie przekazany.
Algorytm ECMAScript dla tworzenia nowych obiektów (czytaj więcej here) stwierdza, że ​​jeśli prototyp funkcji jest ustawiony na null (lub dowolny inny niż obiekt), podczas próby użycia składni new f() nowo utworzony obiekt zostanie dziedziczony po Object.prototype.
Jeśli używasz Object.create(null), nowo utworzony obiekt będzie miał swoją [[Prototype]] wewnętrzny zestaw member aby null, co oznacza łańcuch prototyp będzie tam zatrzymać (Twój obiekt nie dostać hasOwnProperty i inne rzeczy z Object.prototype jak normalny obiekt będzie).

var o1 = create(null); 
var o2 = Object.create(null); 
Object.getPrototypeOf(o1) === Object.prototype // true 
Object.getPrototypeOf(o2) === Object.prototype // false 
Object.getPrototypeOf(o2) === null // true 
Powiązane problemy