2015-07-10 10 views
7

Da quello che so una funzione dovrebbe ereditare le proprietà dal suo oggetto prototype, a cui si può accedere usando la proprietà .prototype o __proto__.__proto__ e differenza prototipo

//my prototype Object 
var myObj = { 
    a: 1, 
    b: 2 
}; 

var myFunc = function() {}; 

// setting function's `prototype` property 
myFunc.prototype = myObj; 
alert(myFunc.a); 
//returns undefined (Why???) I was expecting 1 

Ma quando ho provato la seguente,

//setting function __proto__ property 
myFunc.__proto__ = myObj; 
//returns 1 
alert(myFunc.a); 

Allora perché funziona quando ho impostato myFunc.__proto__ e non quando ho impostato myFunc.prototype?

Ho fatto riferimento a __proto__ VS. prototype in JavaScript ma non ho potuto capire.

+2

http://es5.github.io/ non sa nulla di '__proto__'. Il che significa che non fa parte dello standard e non dovresti mai usarlo. – zerkms

+0

No, il prototipo di un oggetto (quello con cui eredita da) è ** non ** il '.prototype'. Hai letto tutte le risposte a http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript? Cosa non hai capito in modo specifico (siamo felici di migliorarli)? – Bergi

+0

allora che cos'è .prototype usato per ?? – Flake

risposta

15

__proto__

Si può effettivamente accedere alla [[Prototype]] proprietà interna di un oggetto con __proto__. È possibile pensare a [[Prototype]] come padre effettivo dell'oggetto corrente, nella gerarchia di ereditarietà.

prototype

Questa è una proprietà speciale, quando impostato su un oggetto funzione (costruttore), utilizzato per stabilire la catena di ereditarietà di istanze create dal costruttore. Ad esempio,

function Foo() {} 
Foo.prototype = {a: 1}; 

Ora, quando si crea un nuovo oggetto di tipo Foo, [[Prototype]] proprietà interna dell'oggetto appena creato farà riferimento l'oggetto Foo.prototype. È possibile confermare che in questo modo

console.assert((new Foo()).__proto__ === Foo.prototype); 

Nel tuo caso,

myFunc.prototype = myObj; 

si sta creando una proprietà prototype sul oggetto funzione e questo sarà usato solo quando si creano nuovi oggetti con questa funzione (funzione costruttore). Potresti volerlo pensare come modello per i nuovi oggetti. Quindi, quando fai il myFunc.a, il motore JS prova a trovare a nel myFunc e i suoi genitori nella catena del prototipo e non lo trova, ecco perché restituisce undefined.

Ma, quando si fa

myFunc.__proto__ = myObj; 

si sta impostando il genitore di myFunc, nella catena di prototipi, per myObj. Pertanto, quando esegui il comando myFunc.a, il motore JS tenta prima di trovare a nell'oggetto myFunc e non è lì. Quindi, cerca di trovarlo nel suo genitore immediato, che è myObj. Questo è il motivo per cui restituisce 1 in questo caso.


Nota: È possibile utilizzare la seguente funzione per capire la catena di prototipi meglio

function printPrototypeChain(object) { 
    while (object !== null) { 
     console.log(object); 
     object = Object.getPrototypeOf(object); 
    } 
} 

Ora, cerchiamo di stampa della catena di prototipi quando l'oggetto viene impostato come prototype di proprietà della funzione oggetto.

function myFunc() {} 
myFunc.prototype = { 
    a: 1, 
    b: 2 
}; 
printPrototypeChain(myFunc); 

L'uscita sarà

[Function: myFunc] 
[Function: Empty] 
{} 

Nessuno di questi oggetti hanno a definito, così undefined viene restituito. Ma, in questo caso,

function myFunc() {} 
myFunc.__proto__ = { 
    a: 1, 
    b: 2 
}; 
printPrototypeChain(myFunc); 

la catena di prototipi diventa come questo

[Function: myFunc] 
{ a: 1, b: 2 } 
{} 

e a si trova in padre immediato myFunc s'. Quindi, viene restituito il valore corrispondente 1.

Nota: Non utilizzare __proto__ nel codice vero e proprio, in quanto viene mantenuto nelle ultime versioni della specifica JavaScript solo per la compatibilità a ritroso. Per saperne di più su di esso here. Utilizzare invece Object.getPrototypeOf e Object.setPrototypeOf.

+1

due prototipi per una funzione ...... i capperi confondenti !!! – Flake

+0

Quando si esegue myFunc.prototype = myObj; myObj è disponibile per le istanze myFunc e non per myFunc. var x = new myFunc(); console.log (x.a); // restituisce 1 – prgmrDev

0

Stai confondendo myFunc, che è un costruttore, con una esempio di myFunc.

Se si fa qualcosa di simile:

var o = new myFunc(); 
alert(o.a); 

avviserà 1 perché o è un esempio di myFunc, quindi la sua proprietà a deriva dal prototipo myFunc.

Se si imposta __proto__, si sta letteralmente sostituendo il prototipo di funzione che myFunc ereditava da prima e lo sostituiva con l'oggetto prototipo. Di fatto, dopo averlo fatto, qualsiasi metodo che puoi normalmente utilizzare sulle funzioni, come ad esempio call, non verrà più trovato su myFunc.

myFunc.__proto__ = myObj; 
myFunc.call(null); // Will throw an error 
0

oggetti Tutti JS hanno __proto__ proprietà di sistema. Se si tenta di ottenere il valore x corretto di un oggetto a, innanzitutto questa proprietà viene cercata tra le proprietà dell'oggetto a. Se non viene trovato nulla, la proprietà verrà ricercata tra i perietti a.__proto__. E così via. Ecco perché myFunc.a ritorna nel tuo esempio 1. Quando si imposta myFunc.prototype=myObj questo significa che myObj sarà utilizzato in futuro, quando si creano le istanze di myFunc:

var mf = new myFunc(); 

e questo non significa che myFunc deve avere a protpery sé, come ho detto sopra.

Problemi correlati