2012-04-25 31 views
116

Esiste qualche soluzione per ottenere il nome della funzione di un oggetto?Ottieni il nome dell'oggetto o della classe

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) {...} - non v'è alcuna informazione circa la className o ObjectName. È possibile ottenere uno di loro?

+0

Si potrebbe desiderare di vedere questo: http://stackoverflow.com/questions/789675/how-to-get-class-objects-name-as-a-string-in-javascript –

+0

sembra giusto! Molte grazie. ci proverò! – TJR

risposta

204

Ottieni la funzione constructor dell'oggetto e poi ispeziona la sua proprietà name.

myObj.constructor.name 

Restituisce "myClass".

+109

Attenzione! Se stai minimizzando il codice JavaScript, il nome del costruttore cambierà. –

+25

Handy, ma c'è un altro avvertimento: se il tuo oggetto ha un prototipo * chain * (a parte 'Object'), otterrai il nome del * primo * link in quella catena, non il nome del costruttore utilizzato per creare l'oggetto. Prendiamo il seguente esempio: 'function Daddy() {}; function Me() {}; Me.prototype = new Daddy; me = nuovo Me; '. 'me.constructor.name' restituisce inaspettatamente" Papà ", non" Me ". – mklement0

+6

Vale anche la pena di sapere che la proprietà name non è supportata in Jason

15

Esempio:

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

si presenta come quando si utilizza il modello di modulo rivelatore, si otterrà sempre "Oggetto". 'function Foo() {return {'foo': 'bar'}}; var f = new Foo(); ':( –

5

Se si utilizza IIFE standard (ad esempio con il dattiloscritto)

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 = {})); 

si potrebbe annotare i prototipi iniziali con

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

e quindi utilizzare _fullname e _classname fields.

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

funzione di annotazione qui:

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

Questo è troppo intelligente, molto molto utile Grazie – engineforce

+22

E f * cking brutto – maryisdead

4

Prova questo:

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

@ByteHamster Dillo a Google? –

+0

@ByteHamster i tempi cambiano, e le risposte accettate non sono sempre la migliore risposta Non sto dicendo che questo è uno di quei casi, ma cosa succede a te se qualcuno vuole lanciare una nuova risposta per una vecchia domanda? – wallacer

2

stavo affrontando una difficoltà simile e nessuna delle soluzioni presentate qui erano ottimali per quello Stavo lavorando. Quello che avevo era una serie di funzioni per visualizzare il contenuto in una modale e stavo cercando di ridefinirlo con un'unica definizione di oggetto, rendendo le funzioni, i metodi della classe. Il problema arrivò quando scoprii che uno dei metodi creava alcuni pulsanti di navigazione all'interno della stessa modale che usava un onClick su una delle funzioni - ora un oggetto della classe. Ho considerato (e sto ancora considerando) altri metodi per gestire questi pulsanti di navigazione, ma sono stato in grado di trovare il nome della variabile per la classe stessa spazzando le variabili definite nella finestra padre. Quello che ho fatto è stato di ricerca per qualsiasi cosa che corrisponde al 'instanceof' la mia classe, e nel caso in cui ci potrebbe essere più di uno, ho paragonato una proprietà specifica che era probabile essere univoco per ogni istanza:

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

come questo era già stato risposto, volevo solo sottolineare le differenze negli approcci per ottenere il costruttore di un oggetto in JavaScript. C'è una differenza tra il costruttore e l'oggetto/nome della classe reale. Se quanto segue aumenta la complessità della tua decisione, allora forse stai cercando instanceof. O forse dovresti chiederti "Perché sto facendo questo? È davvero questo che sto cercando di risolvere?"

Note:

Il obj.constructor.name non è disponibile sui browser più vecchi. Corrispondenza (\w+) dovrebbe soddisfare le classi di stile ES6.

Codice:

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)); 

Risultato:

enter image description here

Codice: https://jsbin.com/wikiji/edit?js,console

Problemi correlati