如何在Javascript中将类对象的名称作为字符串?

时间:2009-04-25 20:31:09

标签: javascript class

假设我在Javascript中实例化一个对象:

var myObj = new someObject();

现在,是否可以从其中一个类方法中获取var对象的名称作为字符串'myObj'


其他详细信息(已编辑):

我想获取保持对象引用的变量名称的原因是我的新myObj会在页面上创建一个需要调用函数的新的可点击DIV myObj.someFunction()。当我插入新的DIV时,我需要知道保持对象引用的变量的名称。是否有更好的方法可以做到这一点?


你是对的,对不起术语的混淆。

我想得到保持对象引用的变量名称的原因是我的新myObj会在页面上创建一个需要调用函数myObj.someFunction()的新的可点击DIV。当我插入新的DIV时,我需要知道保持对象引用的变量的名称。是否有更好的方法可以做到这一点?

9 个答案:

答案 0 :(得分:43)

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

答案 1 :(得分:19)

简答:编号.myObj不是对象的名称,它是包含对象引用的变量的名称 - 您可以使用任意数量的其他变量来保存对象的引用同一个对象。

现在,如果它是你的程序,那么你制定规则:如果你想说任何给定的对象只会被一个变量引用,并且在你的代码中努力强制执行,那么只需在具有变量名称的对象。

那就是说,我怀疑你所要求的实际上是你真正想要的。也许更详细地描述你的问题......?


Pedantry: JavaScript没有类。 someObject是构造函数。给定对象的引用,您可以使用constructor property获取对创建它的函数的引用。


回应您提供的其他详细信息:

你正在寻找的答案可以在这里找到:JavaScript Callback Scope(并回答关于SO的许多其他问题 - 这对JS新手来说是一个常见的混淆点)。您只需要在闭包中包含对象成员的调用,该闭包保留对上下文对象的访问。

答案 2 :(得分:11)

您可以使用 .toString()将构造函数转换为字符串:

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

答案 3 :(得分: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';

答案 4 :(得分:2)

作为一个更基本的情况,如果this有一个属性可以引用它的引用变量(headstails),那将是很好的但不幸的是它只引用了新的实例化coinSide对象。

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

始终显示

[object Object]

和Firefox的Gecko引擎显示:

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

当然,在此示例中,要解析#1,以及toss,要测试toss==headstoss==tails非常简单。这个问题,实际上是在询问javascript是否具有call-by-name机制,会激发对对手的考虑,是否有call-by-value机制来确定变量的ACTUAL值?该示例演示了headstails的“值”相同,但alert(heads==tails)false

自我引用可以强制如下:
(避免对象空间搜索和How to get class object's name as a string in 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);

显示headstails

这可能是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);
  

有更好的方法......?

“更好”,因为更容易?更容易编程?更容易理解?更快更快地执行?或者是“ ......现在是完全不同的”?

答案 5 :(得分:2)

如果您不想使用Brian的答案中的函数构造函数,则可以使用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()
    }
}

答案 6 :(得分:2)

在对象实例化之后,您可以立即将一个属性(例如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);

答案 7 :(得分:0)

前一段时间,我用过这个。

也许你可以试试:

+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"

答案 8 :(得分:0)

这已经很老了,但是我通过Google遇到了这个问题,所以这个解决方案可能对其他人有用。

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

它只是使用浏览器的JSON解析器和正则表达式,而不会过多地混淆DOM或您的对象。