2013-07-15 13 views
8

Modifica: per coloro che vedono questo post in futuro, this site è stato indubbiamente fondamentale per me per digerire Javascript. Se vieni da uno sfondo tradizionale OOP, lo consiglio vivamente. I diagrammi di UML-esq erano fantastici.Apprendimento .prototype

Non riesco ancora a capire cosa sia la proprietà .prototype in Javascript. È semplicemente un riferimento a un altro oggetto? O è un riferimento a un puntatore a un altro oggetto? Vengo da C/C++/x86 e non riesco a vedere come funziona. Diamo un'occhiata ad alcuni esempi di come attualmente vedo le cose; aiuterebbe a segnalare i miei errori per vedere come funzionano le cose. Non so nemmeno se alcuni di questi sono sintassi valida. Object e Function sono rispettivamente oggetti oggetto/funzione globali.

1          // Global.prototype = ?? 
2          // Function.prototype = ?? 
3 
4 var obj1 = {};      // obj1.prototype = Object 
5 obj2 = {};       // obj2.prototype = Object 
6 
7 var func1 = function() {};   // func1.prototype = Function 
8 func2 = function() {};    // func2.prototype = Function 
9 function func3() {}     // func3.prototype = Function 
10 

Sono così confuso.

11 var Foo = function() { this.prop1 = 0; } 
12 var foo = new Foo();     // should it be 'new Foo' or 'new Foo()'? 
13 // Foo.prototype = Function 
14 // foo.prototype = Foo 
15 var Goo = function() { this.prop2 = 0; } 
16 var goo = new Goo(); 
17 // goo.prototype = Goo 
18 goo.prototype = new Foo(); 
19 // goo.prop1 now exists ? 

Inoltre non capisco lo scambio di prototipi in giro.

20 function A() { 
21  this.prop1 = 1; 
22 } 
23 function B() { 
24  this.prop2 = 2; 
25 } 
26 function C() { 
27  this.prop3 = 3; 
28 } 
29 C.prototype = new B(); 
30 var c = new C(); 
31 // c.prop1 = 1 
32 // c.prop2 = 2 
33 // c.prop3 = undefined 
34 C.prototype = new A(); 
35 // c.prop2 = 2??? 
36 // c.prop3 = 3 

Non riesco a capire il concetto. Non capisco abbastanza. Non capisco come gli oggetti clonati abbiano le loro copie locali dei dati, ma le modifiche all'oggetto originale (il prototipo) in qualche modo ricadono a cascata sui cloni. Sono stato trafficando con FigureBug provare cose fuori, ma mentalmente non posso venire con un'idea che è coerente con tutti gli esempi Ho visto

C++ può essere un enorme mostro, ma almeno so esattamente che succede. Ecco ... Sto usando la mia ipotesi migliore ... Solo un nuovo paradigma, suppongo. Ad ogni modo, grazie se puoi dare una mano ... Sono sottosopra su questo .prototipo.

+0

Controlla la mia risposta in questa domanda: http://stackoverflow.com/questions/17047025/trying-to-understand-javascript-inheritence/17049716#17049716 – Hoffmann

+0

se chiedi obj.x e obj non ce l'ha possedere la proprietà x, JS verificherà l'esistenza di obj.prototype.x e, se presente, restituirà, altrimenti restituisce undefined. pensala come un inoltro di chiamata per la programmazione, il prototipo è un numero alternativo a cui puoi provare a raggiungere i dati. Poiché si tratta di un telefono diverso, puoi comunque chiamare la linea principale se l'alternativa viene distrutta. – dandavis

+0

@dandavis OK Ottengo lo scenario. Cosa non capisco cosa. Riferimenti di prototipi, cosa è impostato per impostazione predefinita, e cosa succede quando inizio a scambiare i prototipi intorno a – gone

risposta

4

Wow, ci sono un sacco di domande. Lavoriamo attraverso di loro.

È semplicemente un riferimento a un altro oggetto? O è un riferimento a un puntatore a un altro oggetto?

Non ci sono puntatori in JavaScript. Tuttavia, una variabile o una proprietà che contiene "un oggetto" contiene effettivamente un riferimento all'oggetto, quindi altre variabili possono contenere riferimenti allo stesso oggetto.

Global.prototype = ?? 

L'oggetto globale (window se volete), in cui sono definite tutte le variabili globali, non ha prototipo (non si preoccupano di eccezioni in alcuni ambienti).

Non riesco ancora a capire cosa sia la proprietà .prototype in Javascript.

La proprietà .prototype è una proprietà che ha tutti gli oggetti funzione, che punta al loro oggetto prototipo (un oggetto semplice).

Non devi confonderlo con il prototipo interno di riferimento che ogni oggetto ha. Il prototipo punta all'oggetto in cui vengono cercate le proprietà che un oggetto non ha esso stesso.

Function.prototype = ?? 

Questo è l'oggetto da cui tutti gli oggetti di funzione ereditano. Contiene cose come call o bind.

var obj1 = {};    // obj1.prototype = Object 
var func1 = function() {}; // func1.prototype = Function 

Sì, un po '. Penso che tu abbia il concetto, ma non conoscessi la terminologia. Mentre func.prototype è una cosa diversa, la proprietà obj.prototype non esiste nemmeno. Tuttavia, intendevi i prototipi interni - possiamo accedervi tramite la funzione Object.getPrototypeOf. E non si riferiscono alle funzioni del costruttore, ma ai loro oggetti prototipo. Ecco la correzione:

Object.getPrototypeOf(obj1) === Object.prototype 
Object.getPrototypeOf(func1) === Function.prototype 

dovrebbe essere 'new Foo' o 'new Foo()'?

Non importa, sono equivalenti. Hai solo bisogno delle parentesi esplicitamente quando vuoi passare argomenti.

var Foo = function() { this.prop1 = 0; } 
var foo = new Foo(); 

Anche in questo caso, le vostre supposizioni erano corretti ma espresso male. Lavoriamo attraverso i dettagli.

Sopra, ho parlato di "oggetti prototipo". Cosa sono quelli? Sono oggetti semplici che vengono creati implicitamente con ogni funzione. In questo caso, è Foo.prototype - un oggetto vuoto. Quindi trattiamo qui tre oggetti: la funzione di costruzione , il suo oggetto prototipo Foo.prototype e l'istanza foo.

Cosa c'è di speciale in foo? È la prima cosa che fa l'operatore new. Quando una funzione viene richiamata come costruttore - con new - si accede alla relativa proprietà .prototype e viene creato un nuovo oggetto con il suo prototipo interno impostato su tale oggetto prototipo. Questa è la cosa miracolosa. Successivamente la funzione viene richiamata nella nuova istanza in modo che this sia il nuovo oggetto; e nel tuo caso crea la proprietà .prop1 nell'istanza. Quindi il risultato viene restituito (e assegnato a foo).

Come utilizzare questa magia adesso? Il punto è creare proprietà sull'oggetto prototipo, che verrà quindi ereditato.

// modify `Foo.prototype`, the object which `foo` inherits from: 
Foo.prototype.prop2 = 1; 
console.log(foo.prop2); // 1! 

anche io non capisco prototipi scambiando intorno.

Il problema è che questo è assolutamente impossibile. Una volta istanziata, la catena di prototipi di un oggetto è abbastanza statica. Tuttavia, non ne hai bisogno spesso.

goo.prototype = new Foo(); 

che non ha funzionato perché la proprietà .prototype non è quello che vi aspettavate.

var c = new C(); 
C.prototype = new A(); 

Questo funziona solo littlebit. Date un'occhiata a ciò che fa new - cerca la proprietà .prototype del costruttore solo una volta. Il prototipo interno rimane bloccato quindi - non si modifica l'istanza c. Tuttavia, se si crea una nuova istanza var d = new C(), questa verrà ereditata dall'istanza A.

Spero che questo aiuti; se hai ulteriori domande, per favore commenta.

+0

Scusa se ho fatto tardi. Ma si. Questo è. "Il problema è che questo è del tutto impossibile": esattamente quello di cui avevo bisogno (insieme a tutto ciò che hai menzionato)> Molto apprezzato; risposta di prima qualità imo – gone

2

Il prototipo viene utilizzato per cercare le proprietà quando l'oggetto stesso non ha definito, durante le letture. Scrive sempre accadere sull'oggetto stesso

Quando si chiama

// An instance of Foo ({prop1:0}) is set as the 
// prototype (to all instances of Goo) 
var goo = new Goo(); 

// 0, from the prototype 
console.log(goo.prop1); 

// Read from the object itself (set in Goo's constructor) 
console.log(goo.prop2); 

// New instance, same prototype as goo 
var goo2 = new Goo(); 
console.log(goo2.prop1) ; // 0, still from the prototype 

// Setting is always at the object level, not the prototype 
goo.prop1 = 5; 

// goo2 is still reading from the prototype 
console.log(goo2.prop1); 

N.B.

Non istanziare la classe genitore solo per impostare l'ereditarietà. Guarda perché qui http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html