Как получить имя объекта класса в виде строки в Javascript?

Скажем, я создаю экземпляр объекта в Javascript следующим образом:

var myObj = new someObject();

Теперь, можно ли получить имя объекта var как строку 'myObj' из одного из методов класса?


Дополнительная информация (отредактирована):

Причина, по которой я хотел бы получить имя ссылки на привязку переменной к объекту, заключается в том, что мой новый myObj создаст новый кликабельный DIV на странице, который должен вызвать функцию myObj.someFunction(). Когда я вставляю новый DIV, мне нужно знать имя переменной, удерживающей ссылку на объект. Может быть, лучший способ сделать это?


Вы правы, извините за смешение терминологии.

Причина, по которой мне хотелось бы получить имя ссылки на привязку переменной к объекту, заключается в том, что мой новый myObj создаст новый кликабельный DIV на странице, который должен был бы вызвать функцию myObj.someFunction(). Когда я вставляю новый DIV, мне нужно знать имя переменной, удерживающей ссылку на объект. Может быть, лучший способ сделать это?

Ответ 1

Shog9 прав, что это не имеет большого смысла спрашивать, поскольку объект может ссылаться на несколько переменных. Если вас это не волнует, и все, что вам нужно, - это найти имя одной из глобальных переменных, относящихся к этому объекту, вы можете сделать следующий взлом:

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 methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"

Обратите внимание, что это уродливый взлом и не должен использоваться в производственном коде. Если имеется несколько переменных, относящихся к объекту, вы не можете определить, какой из них вы получите. Он будет искать только глобальные переменные, поэтому он не будет работать, если переменная локальна для функции. В общем случае, если вам нужно что-то назвать, вы должны передать имя в конструктор при его создании.

изменить. Чтобы ответить на ваши разъяснения, если вам нужно иметь возможность ссылаться на что-то из обработчика событий, вы не должны ссылаться на него по имени, а вместо этого добавить функцию, которая относится к объекту напрямую. Вот быстрый пример того, что я взломал, что, похоже, похоже на то, что вы пытаетесь сделать:

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()
}

Ответ 2

Короткий ответ: Нет. myObj - это не имя объекта, это имя переменной, содержащее ссылку на объект, - вы могли бы иметь любое количество других переменных, содержащих ссылку на тот же объект.

Теперь, если это ваша программа, вы делаете правила: если вы хотите сказать, что любой данный объект будет ссылаться только на одну переменную, когда-либо, и старательно применяйте ее в своем коде, тогда просто установите свойство на объект с именем переменной.

Тем не менее, я сомневаюсь, что вы просите, это на самом деле то, что вы действительно хотите. Может быть, описать вашу проблему немного подробнее...?


Педантизм: В JavaScript нет классов. someObject - это функция-конструктор. Если вы ссылаетесь на объект, вы можете получить ссылку на функцию, которая его создала, используя свойство конструктора .


В ответ на дополнительные данные, которые вы указали:

Ответ, который вы ищете, можно найти здесь: JavaScript Callback Scope (и в ответ на множество других вопросов о SO - это общая точка путаницы для те, которые носят JS). Вам просто нужно обернуть вызов члену объекта в закрытии, который сохраняет доступ к объекту контекста.

Ответ 3

Вы можете сделать это преобразование конструктором в строку с использованием .toString():

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

Ответ 4

Возможно, вы сможете достичь своей цели, используя ее в функции, а затем исследуя источник функции с помощью toString():

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

Ответ 5

В качестве более элементарной ситуации было бы неплохо, чтобы IF this обладал свойством, которое могло ссылаться на него, ссылаясь на переменную (heads или tails), но, к сожалению, она ссылается только на экземпляр нового объекта coinSide.

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

который всегда отображает

[object Object]

и двигатель Firefox Gecko показывают:

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

Конечно, в этом примере, чтобы разрешить #1 и, следовательно, toss, достаточно просто протестировать toss==heads и toss==tails. Этот вопрос, который действительно спрашивает, имеет ли javascript механизм call-by-name, мотивирует рассмотрение партнера, существует ли механизм call-by-value для определения ACTUAL значения переменной? В примере показано, что "значения" как heads, так и tails идентичны, но alert(heads==tails) - false.

Собственная ссылка может быть приведена в порядок следующим образом:
(избегая поиска объектов и возможных двусмысленностей, как указано в Как получить имя объекта класса как строку в решении Javascript?)

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

для отображения heads или tails.

Возможно, это анафема сущности языка Javascript, как интерпретируемого функционального языка прототипирования, чтобы иметь такие возможности, как примитивы.

Окончательное рассмотрение:

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

поэтому, как указано...

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

Есть ли лучший способ...?

"лучше", чем проще? Легче программировать? Легче понять? Легче, чем при более быстром выполнении? Или это как в "... и теперь что-то совершенно другое"?

Ответ 6

Если вы не хотите использовать конструктор функций, например, в ответ Брайана, вы можете использовать Object.create() вместо: -

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

Странно, я не мог заставить выше работать с помощью newDiv.onClick, но он работает с newDiv.addEventListener/newDiv.attachEvent.

Так как Object.create является новым, включите следующий код из Douglas Crockford для старых браузеров, включая IE8.

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

Ответ 7

Сразу же после объекта instantiatd вы можете присоединить к объекту свойство, скажем name, и назначить строковое значение, которое вы ожидаете от него:

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

document.write(myObj.name);

В качестве альтернативы, назначение может быть выполнено внутри кодов класса, то есть

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

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

Ответ 8

Некоторое время назад я использовал это.

Возможно, вы могли бы попробовать:

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

Поставить оповещение: "I get_this_name".

Ответ 9

Это довольно старый, но я столкнулся с этим вопросом через Google, поэтому, возможно, это решение может быть полезно другим.

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

Он просто использует синтаксический анализатор JSON браузера и регулярное выражение, не слишком много загромождая DOM или ваш объект.