2011-08-03 17 views
6

Właśnie dostałem Javascript: The Good Parts Douglasa Crockforda i mam pewne trudności ze zrozumieniem jednego z jego przykładów dotyczących prototypów. Kod w książce brzmi:zamieszanie dotyczące wykonywania javascript

if (typeof Object.create !== "function") { 
    Object.create = function(o) { 
     var F = function() {} 
     F.prototype = o; 
     return new F; 
    }; 
} 

Zakładam, że ten kod jest używany do kierowania na prototyp funkcji. Ale po co używać tak złożonego podejścia? Dlaczego nie po prostu użyć variable .prototypu? Crockford jest wiodącym ekspertem w dziedzinie Javascript, więc jestem pewien, że istnieje dobry powód do korzystania z tego modelu. Czy ktoś może mi pomóc lepiej to zrozumieć? Każda pomoc będzie doceniona.

Odpowiedz

5

W ECMAScript 3, operator new był tylko standardowy sposób ustawić właściwość [[Prototype]]wewnętrznego obiektu, w tym przypadku, Crockforda jest tylko przy użyciu tymczasową funkcję konstruktoraF do tego celu.

o argument tej metody, jest ustawiona jako własność tymczasowej konstruktora prototype i powołując new F(); buduje nowy pusty obiekt, która dziedziczy F.prototype (patrz this question uzyskać więcej informacji o tym, jak new robót).

Na przykład:

var a = { a: 1 }; 
var b = Object.create(a); // b inherits from a 
b.a; // 1 

W powyższym przykładzie, możemy powiedzieć, że wewnętrzne [[Prototype]] punktów obiektu The b „s do a.

Object.getPrototypeOf(b) === a; // true 

Innymi słowy, b dziedziczy z a.

Z tego samego przykładu, możemy używać pustego konstruktora, np

function F(){} 
F.prototype = a; 

var b = new F(); // b again inherits from a (F.prototype) 

Pamiętaj również, że własność funkcji prototype jest inna niż własność [[Prototype]], że wszystkie obiekty mają właściwość funkcji prototype jest używane, gdy są wywoływane z nowym operatorem, w celu zbudowania nowego obiektu, który dziedziczy z tej właściwości.

Należy również pamiętać, że obecnie wdrażana jest norma ECMAScript 5, która nie jest w 100% zgodna ze specyfikacją, w rzeczywistości istnieją pewne cechy standardowej metody Object.createthat cannot be emulated on ES3.

Zobacz także:

+0

@ CMS - ale w tym przypadku "Object.create" jest ustawione na pustą funkcję. Więc tutaj nie ma dziedzictwa ... prawda? Ponadto, ponieważ 'Object.create' jest metodą konstruktora' Object', ustawienie go na wartość pustej funkcji byłoby poprawne? – dopatraman

+0

@codeninja, Nie rozumiem dlaczego mówisz 'Object.create' jest * ustaw * na * pustą * funkcję, może ze względu na ostatnią linię (' return new F; ') ??? Ta ostatnia linia po prostu zwraca nowy obiekt wywołujący konstruktor 'F' (obiekt, który dziedziczy po' F.prototype'), może wyglądać nieznośnie, ponieważ na końcu brakuje nawiasów, ale są one opcjonalne, gdy używasz 'nowego 'operator (' nowy F(); 'jest równoważny' nowemu F; ') ... – CMS

+0

@ CMS - Kod odczytuje' Object.create = var F', który jest ustawiony '=' na 'function() { } '. czy to nie znaczy, że w pewnym sensie jest ustawiony na pustą funkcję? – dopatraman

0

Ta metoda create stworzy instancję nowego obiektu podanego jako przekazany obiekt jako prototyp.

+0

@ Nathan_Romano - dlaczego nie używać po prostu obiektu 'new'? – dopatraman

3
var bar = Object.create(foo) 

vs.

var bar = new Object() 

pierwszy bar ma foo jako jego prototypu; drugi ma Object jako prototyp.

+0

Typo: "drugi ma" Obiekt "jako jego prototyp" powinien być "drugi ma" Object.prototype "jako jego prototyp ..." ("Obiekt" to tylko funkcja konstruktora) – CMS

+0

@ Claudiu - w tym przypadku 'Object.create' jest ustawione na' function() ', nie przypisuje prototypu do żadnej zmiennej. – dopatraman

1

Ten kod jest dla starszych implementacjach JavaScriptu, które nie obsługują Object.create, który jest określony w standardzie ECMAScript 5 zwolniony w listopadzie 2009 r

Wiele osób twierdzi, że preferowanym sposobem tworzenia obiektu jest określenie jego prototypu w momencie tworzenia. Można to nazwać differential inheritance lub prototypal inheritance. W rzeczywistości, to co Object.create robi:

var protoCircle = {x: 0, y: 0, radius: 1, color:"black"}; 
var myCircle = Object.create(protoCircle); 
myCircle.x = 3; 
myCircle.color = "green"; 

To sprawi, zielony okrąg o promieniu 1 i środku w (3,0).

Powodem kod jest tak skomplikowane, że przed Object.create została dodana do JavaScript The Jedynym sposobem, aby ustawić prototyp obiektu było stworzenie go z operatoremnew. Obiekty utworzone za pomocą new otrzymały jako prototyp wartość właściwości konstruktora: prototype. Jest to zdecydowanie mylące, ale właściwość prototype NIE jest prototypem obiektu. Biorąc pod uwagę obiekt funkcji f, f.prototype jest obiektem, który zostanie przypisany jako prototyp wszystkich obiektów zbudowanych za pomocą new f(). Prawdziwy prototyp obiektu nazywa się [[prototype]] lub __proto__, ale nie można uzyskać do niego dostępu w standardowym ECMAScript. Mylące, prawda?

Na marginesie. specyfikacja ES5 ma bardziej rozszerzoną specyfikację Object.prototype niż zdefiniowana Crockford. Zajmuje drugi obiekt do konfiguracji właściwości definiowanego obiektu.