2013-06-30 18 views
7

Se è possibile utilizzare obj.constructor.prototype per accedere al prototipo di un oggetto, perché non è possibile utilizzare obj.constructor.prototype.constructor.prototype per attraversare la catena di prototipi e utilizzare Object.getPrototypeOf?Attraversamento della catena di prototipi utilizzando constructor.prototype

function MyConstructor() 
{ 
    this.prop = 1; 
} 

var o = new MyConstructor(); 

console.log(o.constructor.prototype) // MyConstructor 

console.log(o.constructor.prototype.constructor.prototype) // MyConstructor? 

Non dovrebbe restituire il prototipo di MyConstructor che è function() { [native code] } (in consolle Chrome)?

risposta

7

Tutti i costruttori sono istanze della Function oggetto globale:

function Foo(){ this.x = 1 }; // Dummy constructor function 

console.log(Foo instanceof Function) // => true; Foo is an instance of global Function constructor 

Tutti i prototipi sono istanze della Object oggetto globale:

console.log(Foo.prototype instanceof Object); // => true 

Quando un costruttore Foo è definito, è automaticamente un Foo.prototype oggetto ad esso collegato, che puoi considerare come un oggetto "vuoto" che, come sopra, eredita dall'oggetto globale Object. In altre parole, il prototipo di Foo.prototype è Object.prototype:

function Foo(){ this.x = 1 }; // Dummy constructor function 

console.log(Foo.prototype); // Foo (object); already exists 

console.log(Object.getPrototypeOf(Foo.prototype) === Object.prototype); // => true 

Dal Foo.prototype è un oggetto vuoto, ci si aspetterebbe che il costruttore sia la funzione globale Object costruttore:

function Foo(){ this.x = 1 }; // Dummy constructor function 

console.log(Foo.prototype.constructor) // => function Foo() { this.x = 1; } ?? 

console.log(Foo.prototype.constructor === Object.prototype.constructor); // => false 

Tuttavia, questo "vuoto" l'oggetto ha una proprietà autoreferenziale esplicita constructor che punta a function Foo(){ this.x = 1 } e sovrascrive o "maschera" la proprietà di costruzione predefinita che ci si aspetta:

function Foo(){ this.x = 1 }; // Dummy constructor function 

delete Foo.prototype.constructor; // Delete explicit constructor property 

console.log(Foo.prototype.constructor) // => function Object() { [native code] } 

console.log(Foo.prototype.constructor === Object.prototype.constructor); // => true 

Pertanto non è possibile utilizzare obj.constructor.prototype in modo ricorsivo per attraversare la catena del prototipo e fare affidamento sul metodo Object.getPrototypeOf().

Ecco un ottimo visual reference.

2

Se posso usare obj.constructor.prototype per accedere al prototipo di un oggetto

Non si può in generale. Considerate come funziona questo approccio:

var proto = MyConstructor.prototype; 
// has an (nonenumberable) property "constructor" 
proto.hasOwnProperty("constructor"); // `true` 
// that points [back] to 
proto.constructor; // `function MyConstructor() {…}` 

Come si vede, questa è una struttura di proprietà circolare. Quando si esegue

var o = new MyConstructor(); 
// and access 
o.constructor; // `function MyConstructor() {…}` 
// then it yields the value that is inherited from `proto` 
// as `o` doesn't have that property itself: 
o.hasOwnProperty("constructor"); // `false` 

Ma che funziona solo per oggetto, come o che ereditano la proprietà constructor dal loro oggetto prototipo e dove che ha un valore utile con qualcosa che punta all'oggetto prototipo. Pensa a

var o = {}; 
o.constructor = {prototype: o}; 

Oops. L'accesso a o.constructor.prototype produce qui o e potrebbe essere stato qualsiasi altro valore senza senso. La struttura in realtà è la stessa di sopra con MyConstructor.prototype - e se si accede a proto.constructor.prototype.constructor.prototype[.constructor.prototype…] non si ottiene altro che solo proto.

allora perché non posso usare obj.constructor.prototype.constructor.prototype per attraversare la catena di prototipi e devono usare Object.getPrototypeOf?

Perché si è intrappolati nella struttura circolare, come MyConstructor.prototype) ha quel constructor immobiliare e non ereditato da Object.prototype. Per ottenere veramente il prossimo oggetto la vera catena del prototipo, devi usare Object.getPrototypeOf.

var o = new MyConstructor(); 
console.log(o.constructor.prototype) // MyConstructor 

Avrebbe dovuto essere MyConstructor.prototype realtà. La console di Chrome a volte si confonde nel mostrare titoli utili per oggetti senza nome e, tuttavia, non è sempre corretta.

Se si ottiene il suo prototipo, dovrebbe cedere Object.prototype, e quando si ottiene il prototipo della funzione MyConstructor in sé dovrebbe essere Function.prototype. Si noti che è possibile eseguire quest'ultimo da MyConstructor.constructor.prototype di nuovo ...

Problemi correlati