[英]JavaScript OO issue when accessing instance methods
I've used a few tutorials on OOP in JavaScript. 我使用过一些有关JavaScript中OOP的教程。 It seemed to go well, until I met the following...
一切顺利,直到我遇到了以下问题...
Result of expression 'this.prepareFrame' [undefined] is not a function.
Ok. 好。 I'm using
prototype
and make use of the this
keyword. 我正在使用
prototype
并使用this
关键字。
See my app.js
page here... 在这里查看我的
app.js
页面...
// Plain "main" function called by the html page, like <script>main()</script>. This works nicely:
function main() {
engine = new AbstractEngine();
engine.init();
}
// Next creates a new instance of my AbstractEngine class. Seems to work so far:
function AbstractEngine() {}
// The init() method we called is defined afterwards:
AbstractEngine.prototype.init = function() {
this.initLoop();
}
// remark: I'm using "this", and according to the debugger, "this" refers to the AbstractEngine we made an instance of.
// Next, we define the initLoop method:
AbstractEngine.prototype.initLoop = function() {
setInterval(this.tick, 1000 / 30);
}
// Fine, everything works fine so far. Now get to define the "tick" method:
AbstractEngine.prototype.tick = function() {
this.prepareFrame();
this.update();
}
// Ok, we're in trouble. The error message is output to the console and I don't understand why... The prepareFrame() and update() methods are defined right afterwards:
AbstractEngine.prototype.update = function() {
console.log('updating!');
}
AbstractEngine.prototype.prepareFrame = function() {
console.log('preparing frame');
}
// I read my code twice, but didn't find beginner's mistakes like typo or whatever. But well, cosnider I'm a beginner
You need to change the definition of initLoop
to be the following: 您需要将
initLoop
的定义更改为以下内容:
AbstractEngine.prototype.initLoop = function() {
var that = this;
setInterval(function () {
that.tick();
}, 1000 / 30);
}
This is because the resolution of this
is delayed until execution time and when the interval is executed, this
points to window
, rather than your instance of AbstractEngine
. 这是因为该决议
this
被延迟,直到执行时间和执行的时间间隔时, this
指向window
,而不是你的实例AbstractEngine
。
By wrapping the call to tick
in an anonymous function, we create a closure which allows us to capture that
(which we set to this
). 通过将对
tick
的调用包装在一个匿名函数中,我们创建了一个闭包,它允许我们捕获that
闭包(将其设置为this
)。 By calling the method tick
on the instance that (which is the old this), we can restore the value of "this"). 通过在实例 ( 旧的 this)上调用方法
tick
,我们可以恢复“ this”的值。
This: 这个:
setInterval(this.tick, 1000 / 30);
Should be: 应该:
var that = this;
setInterval(function () { that.tick(); }, 1000 / 30);
or alternately: 或者:
setInterval(this.tick.bind(this), 1000 / 30);
Explanation: when you pass simply this.tick
, that is the same as doing the following: 说明:当您简单地传递
this.tick
,与执行以下操作相同:
var temp = this.tick;
setInterval(temp, 1000 / 30);
But now, when temp
is called, JavaScript doesn't know what the this
pointer should be; 但是现在,当调用
temp
时,JavaScript不知道this
指针应该是什么。 that information gets lost, and it ends up getting bound to the global object ( window
), or to null
if you are in strict mode. 该信息会丢失,最终会绑定到全局对象(
window
),如果处于严格模式下则将绑定为null
。
So you need to somehow ensure that this.tick
is called as a method with the appropriate this
pointer. 因此,您需要以某种方式确保使用适当的
this
指针作为一个方法来调用this.tick
。 There are two ways to do this: 有两种方法可以做到这一点:
var that = this
, you can properly call that.tick
as a method on the original this
pointer. var that = this
的闭包中,您可以正确地调用that.tick
作为原始this
指针上的方法。 bind()
ing the this.tick
function to this
, you ensure it is called as a method with the appropriate this
every time: in other words, you could even do var temp = this.tick.bind(this)
and setInterval(temp, 1000 / 30)
. bind()
将this.tick
函数this
进行调用,可以确保每次都使用适当的this
调用该方法:换句话说,您甚至可以执行var temp = this.tick.bind(this)
和setInterval(temp, 1000 / 30)
。 Note that bind
is not available in older browsers (notably IE <= 8 and all Safaris so far up to and including 5.1), in which case you'd need something like es5-shim . 请注意,
bind
在较旧的浏览器中不可用(特别是IE <= 8以及到目前为止(包括5.1)及以下的所有Safari ),在这种情况下,您将需要es5-shim之类的东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.