2015-10-07 6 views
5

Sto esaminando seriamente la specifica di ECMAScript 5.1.Non c'è modo di trovare il vero costruttore di un oggetto in JavaScript

E io sono curioso di sapere se c'è un modo per dire ciò che il "funzione di costruzione vera e propria" di un oggetto in ES5. (Non esplicita "costruttore" proprietà)

Secondo le specifiche, "costruttore" esplicito struttura dista iniziale indietro richiamo dal sottoprodotto oggetto di un oggetto funzione all'oggetto funzione.

(Qui, il sottoprodotto è l'oggetto che è inizialmente indicato dalla esplicita "prototipo" proprietà dell'oggetto funzione).

Quindi, esplicita "costruttore" la proprietà non ha nulla a che vedere con il vero costruttore di un oggetto:

function Foo(name){ this.name = name; } 
var foo = new Foo("Brian"); 
var bar = { a: 10, b: function(){ if(this.name) return this.name; }}; 
Foo.prototype = bar; 
var foo2 = new Foo("John"); // Let me call Foo as "real constructor" of foo2 

Qui, anche se foo2 è stato creato da Foo, dal momento che Foo.prototype stava indicando al bar al momento della creazione di foo2, in modo da interno [[Prototype]] di foo2 arriva a puntare al bar, e possiamo controllare questo:

Object.getPrototypeOf(foo2) === bar // true 

Dato foo2 non ha proprio "costruttore" di proprietà, come al solito, quindi, la lettura foo2.constructor è in realtà [[Prototype]] lookup catena, cioè foo2.constructor -.> ((Foo2 [[ Prototipo]])). Costruttore -> bar.constructor che è Object, non Foo.

È possibile controllare questo:

foo2.constructor === Foo   // false 
foo2.constructor === Object  // true 

Infine, non c'è un modo per trovare Foo dal foo2 oggetto?

ADD: Sto parlando di ES5. Si prega di non portare nulla di dipendente dal motore o ES6-thingy (ad esempio __proto__)

+2

Beh, ho intenzione di uscire su un arto qui e dire che non è possibile. Per quanto ne so, non c'è nulla che colleghi saldamente la funzione del costruttore con l'oggetto costruito. Puoi cambiare 'Foo.prototype' dopo aver creato l'oggetto e anche' foo2 instanceof Foo' non funzionerà più. Basti pensare alla funzione del costruttore come a una stampa blu. Lo usi per creare un oggetto ma dopo averlo creato, non c'è nulla che ti impedisca di fare cose completamente diverse per entrambi. – basilikum

+0

Inoltre, non dimenticare che è perfettamente possibile per un costruttore restituire un oggetto completamente nuovo al posto dell'implicito 'return this', nel qual caso c'è assolutamente _no link_ alla funzione che lo ha creato. – Alnitak

risposta

4

No, il linguaggio non offre in modo nativo alcuna funzione che lo faccia.

Se consultiamo lo spec on the new operator, vediamo che è in gran parte una chiamata al metodo interno di una funzione [[Construct]]. Volgendo l'attenzione [[Construct]], vediamo:

Quando la [[Costruisce]] metodo interno per un oggetto Function F chiamato con una lista vuota di argomenti, vengono adottate le seguenti fasi:

  1. Let obj essere un oggetto ECMAScript nativo appena creato.
  2. impostare tutti i metodi interni di obj come specificato in 8.12.
  3. Impostare la [[Classe]] proprietà interna di obj a "Object".
  4. Impostare la proprietà interna [[Extensible]] dell'oggetto a true.
  5. Lasciate proto il valore di chiamare la proprietà interna [[Ottieni]] di F con argomento "prototype".
  6. Se Tipo (proto) è oggetto, impostare il [[Prototype]] proprietà interna di obj-proto.
  7. Se Type (proto) non è oggetto, impostare la [[Prototype]] struttura interna obj allo standard incorporato oggetto prototipo oggetto come descritto in 15.2.4.
  8. Let risultato essere il risultato della chiamata al [[Bando]] proprietà interna di F, fornendo obj come questo valore e che fornisce la lista degli argomenti passati in [[Construct]] come args.
  9. Se Tipo (risultato) è Oggetto, quindi restituisce il risultato.
  10. Ritorno obj.

Come si può vedere in passi da 5 a 7, l'unico trattamento dell'oggetto creato da new fa dall'ambiente è quello di impostare la [[Prototype]] e poi passarlo al metodo [[Call]] della funzione per l'elaborazione nella fase 8. Se il valore assegnato all'oggetto [[Prtototype]] non contiene una proprietà accurata constructor, non è possibile sapere quale funzione del costruttore ha creato un oggetto.

Si potrebbe, naturalmente, memorizzare le informazioni nel proprio codice costruttore impostando un valore per l'oggetto al momento della creazione del tempo, ma il motore JavaScript non lo farà per voi.

+0

Ok, ora sembra di nuovo chiaro. In realtà, ero curioso quando la console di Chrome sputava il ** vero costruttore ** correttamente per l'esempio precedente. Quindi, deve essere l'implementazione interna del motore che non è esposta al pubblico. –

Problemi correlati