2012-09-30 8 views
14

Si dice spesso che ogni oggetto Javascript ha una proprietà prototype, ma trovo che foo.prototype abbia un valore solo se foo è una funzione.Si dice che tutti gli oggetti Javascript abbiano una proprietà prototipo, ma vedo solo foo.prototype se foo è una funzione?

Su Chrome e Firefox, obj.__proto__ ha un valore - è questa la proprietà prototype? Ma su IE 9, non funzionerà (c'è un modo che può?), E ho pensato per la proprietà prototype, che significa che obj.prototype dovrebbe funzionare?

Capisco che Object.getPrototypeOf(obj) sembra mostrare questa proprietà prototype, ma perché è necessario un metodo speciale per ottenerlo? Perché non solo come person.name, che è quello di ottenere la proprietà dell'oggetto person?


Aggiornamento: a proposito, obj.constructor.prototype sembra volte essere quel prototipo, ma a volte non, come nel codice seguente fatto con ereditarietà prototipale con nessun costruttore: (questo metodo è nella Pro Javascript design Patterns libro di Harmes e Diaz da Apress 2008, p. 46)

var Person = { 
    name: 'default value', 
    getName: function() { 
     return this.name; 
    } 
} 

var reader = clone(Person); 
console.log(reader.getName()); 
reader.name = "Ang Lee"; 
console.log(reader.getName()); 

function clone(obj) { 
    function F() {}; 
    F.prototype = obj; 
    return new F; 
} 

console.log("the prototype of reader is", Object.getPrototypeOf(reader)); 

console.log(Object.getPrototypeOf(reader) === reader.constructor.prototype); 
console.log(Object.getPrototypeOf(reader) == reader.constructor.prototype); 

console.log(Object.getPrototypeOf(reader) === reader.__proto__); 
console.log(Object.getPrototypeOf(reader) == reader.__proto__); 

il risultato mostrerà falso, falso, vero, vero per gli ultimi 4 linee.

+2

Gli oggetti sono tutti correlati a un prototipo, ma non necessariamente a una proprietà visibile. In altre parole, gli interni del runtime JavaScript sanno qual è l'oggetto prototipo, ma potrebbe non essere possibile per il codice determinare quale sia. Per quanto riguarda * perché * questo è vero, beh, è ​​proprio il modo in cui è stato implementato JavaScript. – Pointy

+2

Chiunque dice che "ogni oggetto JavaScript ha una proprietà prototipo" fa riferimento alla proprietà interna (esposta come '__proto__' sulla maggior parte dei browser, come accennato). –

+1

Dai un'occhiata a questa domanda simile: http://stackoverflow.com/questions/9451881/ –

risposta

13

oggetto Ogni JavaScript ha un "prototipo" interno di proprietà, spesso chiamato [[prototype]], che indica l'oggetto da cui eredita direttamente. Questo è esposto in FF e Chrome dalla proprietà non standard __proto__. Object.getPrototypeOf è un getter per questa proprietà interna.

Ogni funzione JavaScript [oggetto] ha una proprietà prototype, che viene inizializzata con un oggetto [quasi] vuoto. Quando crei una nuova istanza di questa funzione chiamandola come costruttore, [[prototype]] di quel nuovo oggetto punterà all'oggetto prototype del costruttore.

Se si ottiene il [[prototype]] di una funzione (ogni funzione è un oggetto, quindi ha uno), il risultato sarà l'oggetto Function.prototype da cui funzioni ereditano i loro metodi (come bind, chiamata, si applica ecc). Vedi anche Why functions prototype is chained repeatedly? su questo.

+0

vuoi dire con "quasi" oggetto vuoto? come mai hai messo in parentesi quadra? –

+4

L'oggetto quasi vuoto ha una 'funzione di costruzione' non enumerabile su di esso, che punta alla funzione di costruzione. La notazione con le doppie parentesi quadre deriva dalla [specifica ufficiale EcmaScript] (http://ecma-international.org/ecma-262/5.1/#sec-8.6.2) che usa questo formato per tutte le proprietà interne. – Bergi

+0

e la notazione di parentesi "singola" come la tua? [quasi] vuoto –

3

È il constructor di ogni oggetto che ha un prototype. Così per alcuni foo, bar o foobar:

var foo = {}; 
console.log(foo.constructor.prototype); //=> Object 
var bar = 5; 
console.log(bar.constructor.prototype); //=> Number 
function Foobar(){} 
var foobar = new Foobar; //Foobar used a constructor 
console.log(foobar.constructor.prototype); //=> Foobar 
+0

aha, a volte la via del costruttore non funzionerà sembra, per favore vedi l'aggiornamento nella domanda –

+0

@ 動靜 能量 Ecco perché vedi le persone aggiornano manualmente il costruttore quando eseguono l'ereditarietà del prototipo ... qualcosa come '(F.prototype = obj) .constructor = F;' –

Problemi correlati