假设我在Javascript中实例化一个对象:
var myObj = new someObject();
现在,是否可以从其中一个类方法中获取var对象的名称作为字符串'myObj'
?
我想获取保持对象引用的变量名称的原因是我的新myObj
会在页面上创建一个需要调用函数的新的可点击DIV
myObj.someFunction()
。当我插入新的DIV
时,我需要知道保持对象引用的变量的名称。是否有更好的方法可以做到这一点?
你是对的,对不起术语的混淆。
我想得到保持对象引用的变量名称的原因是我的新myObj会在页面上创建一个需要调用函数myObj.someFunction()的新的可点击DIV。当我插入新的DIV时,我需要知道保持对象引用的变量的名称。是否有更好的方法可以做到这一点?
答案 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
有一个属性可以引用它的引用变量(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'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==heads
和toss==tails
非常简单。这个问题,实际上是在询问javascript是否具有call-by-name
机制,会激发对对手的考虑,是否有call-by-value
机制来确定变量的ACTUAL值?该示例演示了heads
和tails
的“值”相同,但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);
显示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);
有更好的方法......?
“更好”,因为更容易?更容易编程?更容易理解?更快更快地执行?或者是“ ......现在是完全不同的”?
答案 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或您的对象。