这是 Javascript 中一个非常常见的错误。我想包括我在内的每个人都曾经这样做过。不过,这很容易理解。
这是怎么回事
当您将函数作为对象的方法调用时,您将其上下文设置为对象。这意味着this
该函数内部将指向您的上下文对象。
MyObject = {};
MyObject.someValue = 1;
MyObject.myMethod = function() {
console.log(this.someValue); // This will log "1" to the console, as expected
};
现在是棘手的部分:您可以更改函数的上下文。让我们在这里添加更多代码行:
MyOtherObject = {};
MyOtherObject.someValue = 2;
MyOtherObject.myMethod = MyObject.myMethod;
当您现在调用时MyOtherObject.myMethod
,您调用的函数与调用 的函数相同MyObject.myMethod
,但在一种情况下this
指向MyObject
,在另一种情况下指向MyOtherObject
。
现在,当您调用 时setInterval(MyObject.myMethod, 1000)
,函数上下文将设置为window
(从技术上讲,setInterval
调用window.setInterval
)并且由于window
没有调用属性someValue
,因此它只是未定义的。
如何修复它
要解决此问题,您可以创建另一个对 LoginScreen 对象的引用。除非您更改它,否则它将始终指向整个范围内的同一个对象。然后,您可以将其用作替代方案,this
而无需担心上下文。
function LoginScreen() {
this.IntervalID = null;
this.counter = 0;
// Create another reference to "this"
var self = this;
this.Start = function () {
// The function behind "this.Update" will always be called with "window"
// as its context.
this.IntervalID = window.setInterval(this.Update, 60 / 1000);
};
this.Stop = function () {
// This function is called as "self.Stop", therefore "this" points to
// "self", which points to the right object, so you can use "this".
clearInterval(this.IntervalID);
};
this.Update = function () {
// Inside this function, "this" points to "window".
// You therefore have to use the previously declared "self"
// to point to the right object.
self.counter++;
alert(self.counter);
if (self.counter > 5) self.Stop();
};
}
LS = new LoginScreen();
LS.Start();
进一步参考
this - Mozilla Developer Network对 JavaScript 中this行为的另一种解释,以及一些控制它的函数。