2010-02-11 9 views
17

Dado el siguiente código:¿Cómo puedo ver la cadena de prototipos de un objeto Javascript?

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

nos podemos quedar a que se ha añadido a b 's cadena de prototipo. Estupendo. Y, todo lo siguiente es cierto:

b1 instanceof b 
b1 instanceof a 
b1 instanceof Object 

Mi pregunta es, ¿y si no sabemos el origen de b1 antes de tiempo? ¿Cómo podemos descubrir a los miembros de su cadena de prototipos? Lo ideal sería que quisiera una matriz como [b, a, Object] o ["b", "a", "Object"].

¿Esto es posible? Creo que he visto una respuesta en algún lugar de SO que describió cómo descubrir esto, pero no puedo encontrarla de nuevo.

Respuesta

2

Puede usar la propiedad "constructor" del objeto para encontrar el prototipo allí, y luego encadenarlo hasta que llegue al final del arcoíris.

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, []); 
} 

(tal vez) (o tal vez no :-) dame un segundo) (así porquería, yo creo que es posible, pero ignoran que el código)

[editar] wow esto está soplando totalmente mi mente - esa función está cerca pero no del todo bien; configurar una cadena de prototipos es extraño y me siento asustado y solo. Sugiero prestar atención solo al increíble @CMS anterior.

+0

'constructor' le da la función constructora del ancestro prototipo más cercano que no ha heredado de otro prototipo de constructor. Esto casi nunca es lo que quieres. Por ejemplo, en el código de la pregunta, 'b1.constructor' es' a', no 'b', y si derivabas un objeto' c' de 'b', un' c1.constructor' seguiría siendo 'a'. Regla general: no use 'constructor' para nada. [eta: lol @ 'miedo y soledad' ... sí, esta es una de esas partes de JavaScript que está diseñada para confundirte al hacer algo que parece útil pero que en realidad es una trampa.] – bobince

+0

Sí, yo Considero la pregunta original un ejercicio interesante, pero nunca fue algo que puse en el código que esperaba que realmente funcionara. Aquí hay una explicación muy buena: http://mckoss.com/jscript/object.htm – Pointy

7

Bueno, el prototipo de enlace entre los objetos ([[Prototype]]) es interno, algunas implementaciones, como el Mozilla, lo exponen como obj.__proto__.

El método Object.getPrototypeOf de ECMAScript 5th Edition es lo que necesita, pero no se implementa ahora en la mayoría de los motores JavaScript.

Dale una mirada a esta implementation por John Resig, tiene una trampa, que se basa en la propiedad constructor de motores que no son compatibles con __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; 
    }; 
    } 
} 

recordar que esto no es 100% fiable, ya que la propiedad constructor es mutable en cualquier objeto.

+2

como cualquier cosa en Javascript mirando las propiedades del objeto y confiando en lo que obtienes es arriesgado :-) – Pointy

+0

Gracias, pero eso me dice que 'a' es un prototipo de' b1' pero nada sobre 'b'. ¿Cómo puedo encontrar que 'b1' es una instancia de' b'? – pr1001

+0

Volver a 'constructor' no solo es incorrecto debido a la manipulación potencial del prototipo, es completamente incorrecto comenzar porque' constructor' no hace lo que uno pensaría que sería (ver comentario más abajo). Esto muestra una sorprendente ignorancia de la funcionalidad básica de JavaScript de Resig; ** no ** use esta secuencia de comandos. La información sobre '__proto__' y' getPrototypeOf' es buena, sin embargo. – bobince

0

Aquí es un punto de partida:

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

Por supuesto esto es muy incompleta, pero creo que va a trabajar en la mayoría de los casos y si alguien quiere añadir a ella que pueden.

Cuestiones relacionadas