it-swarm.com.de

Wie bekomme ich den Namen des Klassenobjekts als Zeichenfolge in Javascript?

Sagen wir, ich instanziiere ein Objekt in Javascript wie folgt:

var myObj = new someObject();

Ist es möglich, den Namen des var-Objekts als Zeichenfolge 'myObj' aus einer der Klassenmethoden zu erhalten?


Zusätzliche Details (bearbeitet):

Der Grund, warum ich den Namen der Variablen erhalten möchte, die einen Verweis auf das Objekt enthält, besteht darin, dass meine neue myObj auf der Seite eine neue anklickbare DIV erstellt, die eine Funktion myObj.someFunction() aufrufen müsste. Beim Einfügen der neuen Variable DIV muss ich den Namen der Variablen kennen, die auf das Objekt verweist. Gibt es vielleicht einen besseren Weg, dies zu tun?


Sie haben recht, entschuldigen Sie die Terminologie.

Der Grund, warum ich den Namen der Variablen erhalten möchte, die einen Verweis auf das Objekt enthält, ist, dass mein neues myObj auf der Seite ein neues anklickbares DIV erstellt, das eine Funktion myObj.someFunction () aufrufen muss. Beim Einfügen des neuen DIV muss ich den Namen der Variablen kennen, die auf das Objekt verweist. Gibt es vielleicht einen besseren Weg, dies zu tun?

40
Miro Solanka

Shog9 hat recht, dass dies nicht sehr sinnvoll ist, da ein Objekt von mehreren Variablen referenziert werden kann. Wenn Sie sich nicht wirklich dafür interessieren und nur den Namen einer der globalen Variablen suchen, die auf dieses Objekt verweist, können Sie den folgenden Hack ausführen:

function myClass() { 
  this.myName = function () { 
    // search through the global object for a name that resolves to this object
    for (var name in this.global) 
      if (this.global[name] == this) 
        return name 
  } 
}
// store the global object, which can be referred to as this at the top level, in a
// property on our prototype, so we can refer to it in our object's methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"

Beachten Sie, dass dies ein hässlicher Hack ist und nicht im Produktionscode verwendet werden sollte. Wenn sich mehr als eine Variable auf ein Objekt bezieht, können Sie nicht sagen, welche Variable Sie erhalten. Es werden nur die globalen Variablen durchsucht, sodass es nicht funktioniert, wenn eine Variable lokal für eine Funktion ist. Wenn Sie etwas benennen müssen, sollten Sie im Allgemeinen den Namen beim Erstellen an den Konstruktor übergeben.

edit : Um auf Ihre Klarstellung zu antworten, wenn Sie von einem Event-Handler auf etwas verweisen müssen, sollten Sie nicht auf den Namen verweisen, sondern eine Funktion hinzufügen, die direkt auf das Objekt verweist. Hier ist ein kurzes Beispiel, das ich aufgeschnappt habe und etwas ähnliches zeigt, was Sie zu tun versuchen:

function myConstructor () {
  this.count = 0
  this.clickme = function () {
    this.count += 1
    alert(this.count)
  }

  var newDiv = document.createElement("div")
  var contents = document.createTextNode("Click me!")

  // This is the crucial part. We don't construct an onclick handler by creating a
  // string, but instead we pass in a function that does what we want. In order to
  // refer to the object, we can't use this directly (since that will refer to the 
  // div when running event handler), but we create an anonymous function with an 
  // argument and pass this in as that argument.
  newDiv.onclick = (function (obj) { 
    return function () {
      obj.clickme()
    }
  })(this)

  newDiv.appendChild(contents)
  document.getElementById("frobnozzle").appendChild(newDiv)

}
window.onload = function () {
  var myVar = new myConstructor()
}
43
Brian Campbell

Kurze Antwort: Nein. MyObj ist nicht der Name des Objekts, sondern der Name einer Variablen, die einen Verweis auf das Objekt enthält - Sie könnten eine beliebige Anzahl anderer Variablen haben, die einen Verweis auf dasselbe Objekt enthalten.

Wenn es sich um Ihr Programm handelt, müssen Sie die Regeln festlegen: Wenn Sie sagen möchten, dass ein bestimmtes Objekt nur von einer Variablen referenziert wird und dies gewissenhaft in Ihrem Code durchgesetzt wird, legen Sie einfach eine Eigenschaft für das Objekt mit der Name der Variablen. 

Das heißt, ich bezweifle, dass Sie fragen, was Sie wirklich wollen. Vielleicht beschreiben Sie Ihr Problem etwas ausführlicher ...?


Pedantry: JavaScript hat keine Klassen. someObject ist eine Konstruktorfunktion. Wenn Sie einen Verweis auf ein Objekt haben, können Sie einen Verweis auf die Funktion erhalten, die das Objekt erstellt hat, indem Sie die Eigenschaft constructor verwenden.


Als Antwort auf die zusätzlichen Angaben, die Sie angegeben haben:

Die Antwort, die Sie suchen, finden Sie hier: JavaScript Callback Scope (und als Antwort auf zahlreiche andere Fragen zu SO - es ist ein allgemeiner Verwirrungspunkt für alle, die neu bei JS sind). Sie müssen den Aufruf des Objektmitglieds nur in eine Schließung einschließen, die den Zugriff auf das Kontextobjekt beibehält.

19
Shog9

Sie können es durch den Konstruktor in einen String konvertieren, indem Sie .toString () verwenden:

function getObjectClass(obj){
   if (typeof obj != "object" || obj === null) return false;
   else return /(\w+)\(/.exec(obj.constructor.toString())[1];}
11
xaguilars

Möglicherweise können Sie Ihr Ziel erreichen, indem Sie es in einer Funktion verwenden und dann die Quelle der Funktion mit toString() untersuchen:

var whatsMyName;

  // Just do something with the whatsMyName variable, no matter what
function func() {var v = whatsMyName;}

// Now that we're using whatsMyName in a function, we could get the source code of the function as a string:
var source = func.toString();

// Then extract the variable name from the function source:
var result = /var v = (.[^;]*)/.exec(source);

alert(result[1]); // Should alert 'whatsMyName';
4
Vidar S. Ramdal

Grundsätzlich wäre es Nizza. IF this hatte eine Eigenschaft, die auf die referenzierende Variable (heads oder tails) verweisen konnte. Leider wird nur auf die Instantiierung des neuen coinSide-Objekts verwiesen.

javascript:  /* it would be Nice but ... a solution NOT! */
function coinSide(){this.ref=this};
/* can .ref be set so as to identify it's referring variable? (heads or tails) */
heads = new coinSide();
tails = new coinSide();
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
alert(["FF's Gecko engine shows:\n\ntoss.toSource()  is  ", toss.toSource()])

was immer angezeigt wird

[object Object]

und Firefox's Gecko-Engine zeigt:

toss.toSource()  is  ,#1={ref:#1#}

Um in diesem Beispiel #1 und somit toss aufzulösen, ist es natürlich einfach, toss==heads und toss==tails zu testen. Diese Frage, die wirklich gefragt wird, ob Javascript einen call-by-name-Mechanismus hat, motiviert die Betrachtung des Gegenstücks. Gibt es einen call-by-value-Mechanismus, um den IST-Wert einer Variablen zu bestimmen? Das Beispiel zeigt, dass die "Werte" von heads und tails identisch sind, alert(heads==tails) jedoch false.

Die Selbstreferenz kann wie folgt gezwungen werden:
(Vermeidung der Objektraumjagd und möglicher Mehrdeutigkeiten wie in Wie erhalte ich den Namen des Klassenobjekts als Zeichenfolge in Javascript? solution)

javascript:
function assign(n,v){ eval( n +"="+ v ); eval( n +".ref='"+ n +"'" ) }
function coinSide(){};
assign("heads", "new coinSide()");
assign("tails", "new coinSide()");
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);

um heads oder tails anzuzeigen.

Es ist vielleicht ein Anathema für das Wesen des Javascript-Designs, als interpretierte funktionale Prototyp-Sprache, um solche Fähigkeiten als Primitive zu haben.

Eine abschließende Überlegung:

 javascript:
     item=new Object(); refName="item"; deferAgain="refName";
     alert([deferAgain,eval(deferAgain),eval(eval(deferAgain))].join('\n'));

so wie vereinbart ...

javascript:
  function bindDIV(objName){ 
    return eval( objName +'=new someObject("'+objName+'")' )
  };
  function someObject(objName){
    this.div="\n<DIV onclick='window.opener."+   /* window.opener - hiccup!! */
               objName+
             ".someFunction()'>clickable DIV</DIV>\n";
    this.someFunction=function(){alert(['my variable object name is ',objName])}
  };
  with(window.open('','test').document){         /*     see above hiccup    */
    write('<html>'+
      bindDIV('DIVobj1').div+
      bindDIV('DIV2').div+
      (alias=bindDIV('multiply')).div+
      'an aliased DIV clone'+multiply.div+
      '</html>');
    close();
  };
  void (0);

Gibt es einen besseren Weg ...?

"besser" als in leichter? Einfacher zu programmieren? Leichter zu verstehen? Einfacher als bei schnellerer Ausführung? Oder ist es wie in "... und jetzt für etwas völlig anderes"?

2
Ekim

Wenn Sie keinen Funktionskonstruktor wie in Brians Antwort verwenden möchten, können Sie stattdessen Object.create () verwenden: -

var myVar = {
count: 0
}

myVar.init = function(n) {
    this.count = n
    this.newDiv()
}

myVar.newDiv = function() {
    var newDiv = document.createElement("div")
    var contents = document.createTextNode("Click me!")
    var func = myVar.func(this)
    newDiv.addEventListener ? 
        newDiv.addEventListener('click', func, false) : 
        newDiv.attachEvent('onclick', func)
    newDiv.appendChild(contents)
    document.getElementsByTagName("body")[0].appendChild(newDiv)
}

myVar.func = function (thys) {
   return function() {
      thys.clickme()
   }
} 

myVar.clickme = function () {
   this.count += 1
   alert(this.count)
}

myVar.init(2)

var myVar1 = Object.create(myVar)
myVar1.init(55) 

var myVar2 = Object.create(myVar)
myVar2.init(150) 

// etc

Seltsamerweise konnte ich das Obige nicht mit newDiv.onClick zum Laufen bringen, aber es funktioniert mit newDiv.addEventListener/newDiv.attachEvent.

Da Object.create neu ist, fügen Sie den folgenden Code von Douglas Crockford für ältere Browser ein, einschließlich IE8.

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o
        return new F()
    }
}
2
Anon

Unmittelbar nachdem das Objekt instantiatd ist, können Sie dem Objekt eine Eigenschaft, z. B. name, hinzufügen und den erwarteten Zeichenfolgenwert zuweisen:

var myObj = new someClass();
myObj.name="myObj";

document.write(myObj.name);

Alternativ kann die Zuordnung innerhalb der Codes der Klasse erfolgen, d. H.

var someClass = function(P)
{ this.name=P;
  // rest of the class definition...
};

var myObj = new someClass("myObj");
document.write(myObj.name);
2
kaimagpie

Vor einiger Zeit habe ich das benutzt. 

Vielleicht könnten Sie versuchen:

+function(){
    var my_var = function get_this_name(){
        alert("I " + this.init());
    };
    my_var.prototype.init = function(){
        return my_var.name;
    }
    new my_var();
}();

Pop eine Warnung : "I get_this_name".

0
funnynico

Dies ist ziemlich alt, aber ich bin über Google auf diese Frage gestoßen, daher könnte diese Lösung für andere nützlich sein.

function GetObjectName(myObject){
    var objectName=JSON.stringify(myObject).match(/"(.*?)"/)[1];
    return objectName;
}

Es verwendet lediglich den JSON-Parser und die reguläre Ausdrücke des Browsers, ohne das DOM oder Ihr Objekt zu sehr zu stören.

0
longestwayround