2012-04-25 23 views
116

¿Hay alguna solución para obtener el nombre de la función de un objeto?Obtener el nombre del objeto o clase

function alertClassOrObject (o) { 
    window.alert(o.objectName); //"myObj" OR "myClass" as a String 
} 

function myClass() { 
    this.foo = function() { 
     alertClassOrObject(this); 
    } 
} 

var myObj = new myClass(); 
myObj.foo(); 

for (var k in this) {...} - no hay información sobre el className o ObjectName. ¿Es posible obtener uno de ellos?

+0

Es posible que desee ver esto: http://stackoverflow.com/questions/789675/how-to-get-class-objects-name-as-a-string-in-javascript –

+0

parece correcto! Muchas gracias. ¡Intentaré esto! – TJR

Respuesta

204

Obtiene la función constructor de su objeto y luego inspecciona su propiedad name.

myObj.constructor.name 

Devuelve "myClass".

+109

¡Ten cuidado! Si está minificando el JavaScript, el nombre del constructor cambiará. –

+25

Práctico, pero hay otra advertencia: si su objeto tiene un prototipo * cadena * (aparte de 'Objeto'), obtendrá el nombre del * primer * enlace en esa cadena, no el nombre del constructor utilizado para crear el objeto. Tome el siguiente ejemplo: 'function Daddy() {}; function Me() {}; Me.prototype = new Daddy; me = nuevo Yo; '. 'me.constructor.name' luego inesperadamente devuelve' 'Daddy'', no '' Me''. – mklement0

+6

También vale la pena saber que la propiedad de nombre no es compatible con Jason

15

Ejemplo:

function Foo() { ... } 
var Bar = function() { ... } 
var Abc = function Xyz() { ... } 

var f = new Foo(); 
var b = new Bar(); 
var c = new Abc(); 

alert(f.constructor.name); // -> "Foo" 
alert(b.constructor.name); // -> "Function" 
alert(c.constructor.name); // -> "Xyz" 
+0

parece que al usar el patrón revelador del módulo, siempre obtendrá "Objeto". 'function Foo() {return {'foo': 'barra'}}; var f = new Foo(); ':( –

5

Si utiliza IIFE estándar (por ejemplo, con texto mecanografiado)

var Zamboch; 
(function (_Zamboch) { 
    (function (Web) { 
     (function (Common) { 
      var App = (function() { 
       function App() { 
       } 
       App.prototype.hello = function() { 
        console.log('Hello App'); 
       }; 
       return App; 
      })(); 
      Common.App = App; 
     })(Web.Common || (Web.Common = {})); 
     var Common = Web.Common; 
    })(_Zamboch.Web || (_Zamboch.Web = {})); 
    var Web = _Zamboch.Web; 
})(Zamboch || (Zamboch = {})); 

usted podría anotar los prototipos iniciales con

setupReflection(Zamboch, 'Zamboch', 'Zamboch'); 

y luego usar _fullname y _campos de nombre de clase

var app=new Zamboch.Web.Common.App(); 
console.log(app._fullname); 

función de anotar aquí:

function setupReflection(ns, fullname, name) { 
    // I have only classes and namespaces starting with capital letter 
    if (name[0] >= 'A' && name[0] <= 'Z') { 
     var type = typeof ns; 
     if (type == 'object') { 
      ns._refmark = ns._refmark || 0; 
      ns._fullname = fullname; 
      var keys = Object.keys(ns); 
      if (keys.length != ns._refmark) { 
       // set marker to avoid recusion, just in case 
       ns._refmark = keys.length; 
       for (var nested in ns) { 
        var nestedvalue = ns[nested]; 
        setupReflection(nestedvalue, fullname + '.' + nested, nested); 
       } 
      } 
     } else if (type == 'function' && ns.prototype) { 
      ns._fullname = fullname; 
      ns._classname = name; 
      ns.prototype._fullname = fullname; 
      ns.prototype._classname = name; 
     } 
    } 
} 

JsFiddle

+0

Esto es demasiado inteligente, muy muy útil. Gracias. – engineforce

+22

Y f * cking feo. – maryisdead

4

Prueba esto:

var classname = ("" + obj.constructor).split("function ")[1].split("(")[0]; 
+2

@ByteHamster Dígale que a Google? –

+0

@ByteHamster veces cambian, y las respuestas aceptadas no son siempre la mejor respuesta. No digo que este sea uno de esos casos, pero ¿qué le importa si alguien quiere arrojar una nueva respuesta para una vieja pregunta? – wallacer

2

que estaba frente a una dificultad similar y ninguna de las soluciones que aquí se presentan fueron óptima para lo Estaba trabajando en. Lo que tenía era una serie de funciones para mostrar el contenido en un modal y yo estaba tratando de refactorizarlo bajo una única definición de objeto haciendo las funciones, los métodos de la clase. El problema vino cuando encontré uno de los métodos creados algunos botones de navegación dentro del modal que usaba un onClick para una de las funciones, ahora un objeto de la clase. He considerado (y sigo considerando) otros métodos para manejar estos botones de navegación, pero pude encontrar el nombre de la variable para la clase en sí misma al recorrer las variables definidas en la ventana principal. Lo que hice fue buscar cualquier cosa que coincide con el 'instanceof' mi clase, y en caso de que puede haber más de uno, que comparó una propiedad específica que era probable que sea única para cada instancia:

var myClass = function(varName) 
{ 
    this.instanceName = ((varName != null) && (typeof(varName) == 'string') && (varName != '')) ? varName : null; 

    /** 
    * caching autosweep of window to try to find this instance's variable name 
    **/ 
    this.getInstanceName = function() { 
     if(this.instanceName == null) 
     { 
      for(z in window) { 
       if((window[z] instanceof myClass) && (window[z].uniqueProperty === this.uniqueProperty)) { 
        this.instanceName = z; 
        break; 
       } 
      } 
     } 
     return this.instanceName; 
    } 
} 
4

Como este ya fue respondida, solo quería señalar las diferencias en los enfoques para obtener el constructor de un objeto en JavaScript. Hay una diferencia entre el constructor y el nombre real del objeto/clase. Si lo siguiente se suma a la complejidad de su decisión, entonces tal vez esté buscando instanceof. O tal vez deberías preguntarte "¿Por qué estoy haciendo esto? ¿Esto es realmente lo que trato de resolver?"

Notas:

El obj.constructor.name no está disponible en los navegadores antiguos. Coincidencia (\w+) debe satisfacer las clases de estilo ES6.

Código:

var what = function(obj) { 
    return obj.toString().match(/ (\w+)/)[1]; 
}; 

var p; 

// Normal obj with constructor. 
function Entity() {} 
p = new Entity(); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p)); 

// Obj with prototype overriden. 
function Player() { console.warn('Player constructor called.'); } 
Player.prototype = new Entity(); 
p = new Player(); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p)); 

// Obj with constructor property overriden. 
function OtherPlayer() { console.warn('OtherPlayer constructor called.'); } 
OtherPlayer.constructor = new Player(); 
p = new OtherPlayer(); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p)); 

// Anonymous function obj. 
p = new Function(""); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p)); 

// No constructor here. 
p = {}; 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p)); 

// ES6 class. 
class NPC { 
    constructor() { 
    } 
} 
p = new NPC(); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p)); 

// ES6 class extended 
class Boss extends NPC { 
    constructor() { 
    super(); 
    } 
} 
p = new Boss(); 
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p)); 

Resultado:

enter image description here

Código: https://jsbin.com/wikiji/edit?js,console

Cuestiones relacionadas