Relazione tra [[Prototipo]] e prototipo in JavaScript
-
23-08-2019 - |
Domanda
Da http://www.jibbering.com/faq/faq_notes/closures.html :
Nota:ECMAScript definisce una proprietà interna [[prototipo]] del tipo Oggetto interno.Questa proprietà non è direttamente accessibile con gli script, ma è la catena di oggetti a cui si fa riferimento con la proprietà interna [[prototype]] che viene utilizzata nella risoluzione della funzione di accesso alle proprietà;la catena del prototipo dell'oggetto.Esiste una proprietà pubblica del prototipo per consentire l'assegnazione, la definizione e la manipolazione dei prototipi in associazione con la proprietà interna [[prototipo]]. I dettagli della relazione tra due sono descritti nell'ECMA 262 (3a edizione) e vanno oltre lo scopo di questa discussione.
Quali sono i dettagli del rapporto tra i due?Ho sfogliato l'ECMA 262 e tutto quello che ho letto è cose come:
È possibile fare riferimento al prototipo associato al costruttore tramite l'espressione del programma costruttore.prototipo,
Gli oggetti ECMAScript nativi hanno una proprietà interna chiamata [[Prototipo]].Il valore di questa proprietà è null o un oggetto e viene utilizzato per implementare l'ereditarietà.
Ogni funzione incorporata e ogni costruttore incorporato ha l'oggetto prototipo Function, che è il valore iniziale dell'espressione Function.prototype
Ogni oggetto prototipo incorporato ha l'oggetto prototipo di oggetto, che è il valore iniziale dell'oggetto di espressione. Prototipo (15.3.2.1), come valore della sua proprietà interna [[prototipo]], ad eccezione dell'oggetto prototipo di oggetto stesso.
Da ciò tutto ciò che deduco è che la proprietà [[Prototype]] è equivalente a prototype
proprietà praticamente per qualsiasi oggetto.Mi sbaglio?
Soluzione
Credo che tu abbia ragione nella maggior parte dei casi.
Ogni oggetto ha un nascosto [[Prototype]]
proprietà, che viene utilizzata per l'eredità.Le funzioni hanno inoltre un pubblico prototype
proprietà, che viene utilizzata solo quando la funzione viene utilizzata come costruttore:Quando un oggetto viene costruito utilizzando new
, IL [[Prototype]]
la proprietà del nuovo oggetto è impostata su prototype
proprietà della funzione utilizzata come costruttore.
Per esempio.
function C() {}
C.prototype = P1;
var obj = new C(); // obj.[[Prototype]] is now P1.
Puoi ottenere il [[Prototype]]
proprietà utilizzando Object.getPrototypeOf(<obj>)
.(Questo metodo è specificato in ECMAScript 5.Le versioni precedenti di JavaScript non hanno alcun modo di lettura standard [[Prototype]]
).
Puoi Generalmente arrivare al prototipo attraverso il costruttore, ad esempio:
obj.constructor.prototype == Object.getPrototypeOf(obj)
Ma non è sempre così, poiché la proprietà prototipo della funzione di costruzione può essere riassegnata, ma il file [[Prototype]]
di un oggetto non può essere riassegnato dopo la creazione dell'oggetto.Quindi se lo fai:
C.prototype = P2;
Poi
obj.constructor.prototype != Object.getPrototypeOf(obj)
Perché il prototipo di C
è ora P2
, Ma [[Prototype]]
Di obj
è ancora P1
.
Nota che lo è soltanto funzioni che hanno a prototype
proprietà.Si noti inoltre che il prototype
la proprietà di una funzione non è la stessa di [[Prototype]]
proprietà della funzione!
Altri suggerimenti
Per rispondere direttamente alla tua domanda:logicamente è la copia privata di un oggetto del file prototype
proprietà del suo costruttore.Usando il metalinguaggio ecco come vengono creati gli oggetti:
// not real JS
var Ctr = function(...){...};
Ctr.prototype = {...}; // some object with methods and properties
// the object creation sequence: var x = new Ctr(a, b, c);
var x = {};
x["[[prototype]]"] = Ctr.prototype;
var result = Ctr.call(x, a, b, c);
if(typeof result == "object"){ x = result; }
// our x is fully constructed and initialized at this point
A questo punto possiamo modificare il prototipo, e il cambiamento si rifletterà su tutti gli oggetti della classe, perché fanno riferimento al prototipo tramite riferimento:
Ctr.prototype.log = function(){ console.log("...logging..."); };
x.log(); // ...logging..
Ma se cambiamo il prototipo nel costruttore, gli oggetti già creati continueranno a fare riferimento al vecchio oggetto:
Ctr.prototype = {life: 42};
// let's assume that the old prototype didn't define "life"
console.log(x.life); // undefined
x.log(); // ...logging...
Nel pieno rispetto della norma [[prototype]]
non è disponibile, ma Mozilla estende lo standard con __proto__
proprietà (sola lettura), che espone il file normalmente nascosto [[prototype]]
:
- la documentazione di Mozilla
- panoramica delle estensioni di Mozilla:__count__, __proto__, __genitore__
Ancora, __proto__
può essere legalizzato il prossimo standard ES3.1.
Oltre alla risposta di olavk:Alcune implementazioni JavaScript (es mozilla) consentono di accedere direttamente alla proprietà [[Prototype]]...