2010-02-11 8 views
17

Dato il seguente codice:Come posso vedere la catena di prototipi di un oggetto Javascript?

function a() {} 
function b() {} 
b.prototype = new a(); 
var b1 = new b(); 

possiamo stare che a è stato aggiunto a b s' prototipo catena. Grande. E, tutte le seguenti condizioni:

b1 instanceof b 
b1 instanceof a 
b1 instanceof Object 

La mia domanda è, che cosa se non sappiamo le origini di b1 prima del tempo? Come possiamo scoprire i membri della sua catena di prototipi? Idealmente mi piacerebbe un array come [b, a, Object] o ["b", "a", "Object"].

È possibile? Credo di aver visto una risposta da qualche parte su SO che ha descritto come scoprire solo questo, ma non posso per la vita di me ritrovarlo.

risposta

2

È possibile utilizzare la proprietà "costruttore" dell'oggetto per trovare il prototipo lì, e quindi concatenarlo fino a raggiungere la fine dell'arcobaleno.

function getPrototypes(o) { 
    return (function gp(o, protos) { 
    var c = o.constructor; 
    if (c.prototype) { 
     protos.push(c.prototype); 
     return gp(c.prototype, protos); 
    } 
    return protos; 
    })(o, []); 
} 

(forse) (o forse no :-) mi invia un sec) (bene merda, penso che sia possibile, ma ignorano che il codice)

[modifica] Wow questo è totalmente soffia la mia mente - quella funzione è vicina ma non del tutto corretta; creare una catena di prototipi è strano e mi sento spaventato e solo. Suggerisco di prestare attenzione solo al fantastico @CMS sopra.

+0

'costruttore 'fornisce la funzione di costruzione del prototipo antenato più vicino che non ha ereditato da un altro prototipo di costruttore. Questo non è quasi mai quello che vuoi. Per esempio nel codice della domanda, 'b1.constructor' è' a', non 'b', e se hai derivato un oggetto' c' da 'b', un' c1.constructor' sarebbe ancora 'a'. Normale regola pratica: non usare 'costruttore 'per qualcosa di mai. [eta: lol @ 'spaventato e solitario' ... sì, questa è una di quelle parti di JavaScript che è stata progettata per confondervi da capo facendo qualcosa che sembra utile ma in realtà è una trappola.] – bobince

+0

Sì, I considera la domanda originale un esercizio interessante ma non è mai qualcosa che avrei inserito nel codice che mi aspettavo di funzionare effettivamente. C'è una spiegazione molto bella qui: http://mckoss.com/jscript/object.htm – Pointy

7

Bene, il collegamento prototipo tra oggetti ([[Prototype]]) è interno, alcune implementazioni, come Mozilla, lo espongono come obj.__proto__.

Il metodo Object.getPrototypeOf della ECMAScript 5th Edition è ciò di cui hai bisogno, ma non è implementato in questo momento sulla maggior parte dei motori JavaScript.

Date uno sguardo a questo implementation da John Resig, ha una trappola, si basa sul constructor proprietà di motori che non supportano __proto__:

if (typeof Object.getPrototypeOf !== "function") { 
    if (typeof "test".__proto__ === "object") { 
    Object.getPrototypeOf = function(object){ 
     return object.__proto__; 
    }; 
    } else { 
    Object.getPrototypeOf = function(object){ 
     // May break if the constructor has been tampered with 
     return object.constructor.prototype; 
    }; 
    } 
} 

ricordare che questo è affidabile al 100%, poiché la proprietà constructor è modificabile su qualsiasi oggetto.

+2

proprio come qualsiasi cosa in Javascript guardando le proprietà degli oggetti e confidando in ciò che ottieni è rischioso :-) – Pointy

+0

Grazie, ma questo mi dice che 'a' è un prototipo di' b1' ma niente di 'b'. Come posso scoprire che 'b1' è un'istanza di' b'? – pr1001

+0

Ritornare a 'costruttore 'non è solo sbagliato a causa della potenziale manomissione del prototipo, è completamente sbagliato, perché' costruttore' non fa ciò che penseresti sarebbe (vedi commento sotto). Ciò mostra una sorprendente ignoranza delle funzionalità JavaScript di base di Resig; ** non usare ** questo script. Le informazioni su '__proto__' e' getPrototypeOf' sono buone, comunque. – bobince

0

Qui è un punto di partenza:

Object.prototype.getConstructorNames=function(){ 
     return Object.keys(window).filter(function(e){ 
      return typeof window[e]==="function" && this instanceof window[e]},this) 
    } 

Naturalmente questo è davvero incompleta ma penso che funzionerà nella maggior parte dei casi, e se qualcuno vuole aggiungere ad essa possono.

Problemi correlati