所以,这可能是在这个网站的某个地方回答的,但我找不到它,如果是的话。
我无法弄清楚为什么在创建对象时我的函数内部的this
引用似乎已被解析,而当我调用其中包含引用的函数时,我的函数就被解析了。这是一些代码:
function MyObj (name) {
this.locked = false;
this.name = name;
this.elem = null;
this.func1 = function () {
if (this.locked) return;
/* code that changes this.name here */
this.elem.innerHTML = this.name;
};
this.func2 = function () {
this.locked = !this.locked;
if (this.locked) this.elem.className = "locked";
else this.elem.className = "unlocked";
};
}
var myObjGlobal = new MyObj("foo");
function callFunc1 () {
myObjGlobal.func1();
}
然后我有一个在文档加载时调用的函数:
function onLoad() {
var myElem = document.getElementById("myElem");
myObjGlobal.elem = myElem;
myElem.onclick = myObjGlobal.func2;
document.getElementById("myButton").onclick = callFunc1;
}
我确保所有的html元素都有正确的ID。当我点击myButton
时,我没有收到任何错误。但是,当我点击myElem
时,我会得到Uncaught TypeError: Cannot set property 'className' of undefined
。
为什么在调用函数时设置第一个this
,在创建对象时设置第二个this
? (或者似乎呢?)
这是显示问题的working jsfiddle(使用给定的示例代码)。
提前致谢!
答案 0 :(得分:3)
myElem.onclick = myObjGlobal.func2;
这并不是你认为的JavaScript所做的。它没有给你func2
对象"附加"以任何方式;它只是给你func2
。当它稍后被调用时,它被称为myElem
的方法,因此this
是什么。
这是JS中一个巨大且可怕的瑕疵。 :)
您可以将其包装在另一个函数中:
myElem.onclick = function() {
myObjGlobal.func2();
};
或者使用.bind
,它实际上做同样的事情,现在普遍支持几乎:
myElem.onclick = myObjGlobal.func2.bind(myObjGlobal);
另请注意,分配给onclick
有点粗鲁,因为您将破坏任何现有的点击处理程序。您可能需要addEventListener
。
答案 1 :(得分:2)
myElem.onclick = myObjGlobal.func2;
这完全失去了myObjGlobal
; myObjGlobal.func2
只是一个函数,没有任何东西将this
绑定到任何东西上。在JavaScript中,函数的this
在被调用时确定,而不是在定义时确定。这是JavaScript的一个非常有用的功能,比Python更直观。调用myElem.onclick
时,系统会调用this
绑定myElem
。
Function.prototype.bind
是一个实用程序,用于执行您使用callFunc1
执行的操作,顺便说一下:
myElem.onclick = myObjGlobal.func2.bind(myObjGlobal);