2012-04-26 15 views
10
var someObj = function() { } 
var p = new someObj(); 

alert(someObj.prototype); // This works 
alert(p.prototype);   // UNDEFINED, but why? 

someObj.prototype.model= "Nissan"; 
alert(p.model);    // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype? 

Perché è così? Poiché "p" è un'istanza di "someObj", perché il prototipo è indefinito? Voglio dire, quando aggiungo una proprietà al prototipo "someObj", è accessibile a "p", quindi perché il prototipo non è accessibile?Prototipo Javascript tramite Object.create()

risposta

11

L'importante è che la proprietà prototype degli oggetti funzione non sia il prototipo di un oggetto. È l'oggetto che verrà assegnato come prototipo di un oggetto creato tramite new someObj. Prima di ES5, non è possibile accedere direttamente al prototipo di un oggetto; a partire da ES5, è possibile, tramite Object.getPrototypeOf.

Re

alert(p.prototype); // UNDEFINED, but why?

La ragione è che l'oggetto p non ha una proprietà chiamata "prototipo". Ha un prototipo sottostante, ma non è così che lo si accede.

Tutti gli oggetti funzione hanno una proprietà denominata prototype in modo che se vengono utilizzate come funzioni di costruzione, è possibile definire quali saranno le proprietà del prototipo sottostante degli oggetti creati da tali costruttori. Questo può aiutare:

function Foo() { 
} 
Foo.prototype.answer = 42; 

console.log(Foo.prototype.answer); // "42" 
var f = new Foo(); 
console.log(f.answer); // "42" 

L'ultima linea funziona in questo modo:

  1. ottenere l'oggetto f.
  2. f ha la sua proprietà denominata "risposta"?
  3. No, lo f ha un prototipo?
  4. Sì, il prototipo ha la sua proprietà denominata "risposta"?
  5. Sì, restituisce il valore di tale proprietà.

Hai menzionato Object.create nel titolo della tua domanda. È importante capire che Object.create è piuttosto separato dalle funzioni del costruttore. È stato aggiunto alla lingua in modo tale che se si preferisse non utilizzare le funzioni di costruzione, non era necessario, ma si poteva comunque impostare direttamente il prototipo di un oggetto   —, quando si creava quell'oggetto.

+0

Ottima spiegazione –

+0

@TahaAhmad: Sono contento che abbia aiutato! –

2

p.prototype non funziona perché in questo caso p = someObj.prototype.

In pratica quando si utilizza il nuovo operatore, ciò che accade è che il costruttore someObj viene utilizzato per inizializzare un nuovo oggetto. Il che significa che restituisce un oggetto che ha le proprietà e i metodi del prototipo del costruttore.

Quindi p = someObj.prototype e p.prototype non sono definiti poichè p non è un costruttore.

Questo articolo potrebbe aiutare lo spiega più

http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD

+0

Per risposta di Crowder, il prototipo è lì ed è accessibile, tramite l'uso di Object.getPrototypeOf (p). Se la mia comprensione è corretta, che le proprietà e i metodi vengono copiati in nuove istanze di oggetti, ma ciò non significa che p === someObj.prototype. Significa p.prototype === someObj.prototype –

1

p è un esempio di someObj. Il prototipo appartiene al costruttore. È possibile recuperare prototipo costruttore p s' utilizzando p.constructor.prototype

6

Questo perché prototype è una proprietà della funzione di costruzione, non una proprietà di se stesso. Tuttavia, l'oggetto prototype ha un riferimento al costruttore, in modo da poter accedere di prototype un oggetto tramite la sua proprietà constructor:

function Foo() {} 

Foo.prototype.foo = "bar"; 

var c = new Foo; 

console.log(c.constructor === Foo); // true 
console.log(c.constructor.prototype); // { foo: 'bar' } 

Tuttavia, questo non funzionerà se si sovrascrive il prototype di proprietà iniziale della funzione di costruzione:

function Foo() {} 

// I overwrite the prototype property, so I lose the initial reference 
// to the constructor. 
Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 

Ecco perché è meglio usare il nuovo metodo Object.getPrototypeOf introdotto in ES5.

function Foo() {} 

Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 
console.log(Object.getPrototypeOf(c)); // { foo: 'bar' } 

Un'altra soluzione sarebbe stata quella di fare in modo di ripristinare il riferimento constructor sul prototipo:

function Foo() {} 

// Overwriting the initial prototype  
Foo.prototype = { 
    constructor: Foo, // restore the constructor reference 
    foo: "bar" 
}; 
+0

Ho trovato un blog post estremamente utile che, unito a questa risposta, chiarisce un sacco di confusione sull'intera follia del prototipo. http://blog.sklambert.com/javascript-prototype/ i diagrammi aiutano molto nella comprensione di questa risposta. Spero che questo aiuti qualcuno. – Bruce

0

in JavaScript, costruttori, e infatti tutte le funzioni di ottenere una proprietà prototipo. Un oggetto (cioè un insieme di coppie chiave-valore), non ha una proprietà prototipo. Nel tuo esempio sopra,

var someObj = function() { } // this is a function, so it has a prototype property 
var p = new someObj(); // this is an instance object, so it doesn't 

Ecco perché someObj.prototype è definito, ma non è p.prototype.

Problemi correlati