我在JavaScript中使用了一些关于OOP的教程。它似乎顺利,直到我遇到以下......
Result of expression 'this.prepareFrame' [undefined] is not a function.
确定。我正在使用prototype
并使用this
关键字。
请在此处查看我的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
答案 0 :(得分:4)
您需要将initLoop
的定义更改为以下内容:
AbstractEngine.prototype.initLoop = function() {
var that = this;
setInterval(function () {
that.tick();
}, 1000 / 30);
}
这是因为this
的分辨率被延迟到执行时间和执行间隔时,this
指向window
,而不是AbstractEngine
的实例。
通过在匿名函数中包含对tick
的调用,我们创建了一个闭包,允许我们捕获that
(我们设置为this
)。通过调用实例上的方法 tick
(这是旧这个),我们可以恢复“this”的值“)。
答案 1 :(得分:1)
此:
setInterval(this.tick, 1000 / 30);
应该是:
var that = this;
setInterval(function () { that.tick(); }, 1000 / 30);
或者:
setInterval(this.tick.bind(this), 1000 / 30);
说明:当您简单地传递this.tick
时,这与执行以下操作相同:
var temp = this.tick;
setInterval(temp, 1000 / 30);
但现在,当调用temp
时,JavaScript不知道this
指针应该是什么;该信息会丢失,并且如果您处于严格模式,它最终会绑定到全局对象(window
)或null
。
因此,您需要以某种方式确保将this.tick
作为具有适当this
指针的方法调用。有两种方法可以做到这一点:
var that = this
的闭包中,您可以正确地调用that.tick
作为原始this
指针上的方法。bind()
将this.tick
功能this
发送到this
,您确保每次都使用适当的var temp = this.tick.bind(this)
将其称为方法:换句话说,您可以甚至可以setInterval(temp, 1000 / 30)
和bind
。请注意,{{1}}在旧版浏览器中不可用(特别是IE&lt; = 8和迄今为止所有的Safaris,包括5.1),在这种情况下,您需要es5-shim之类的内容。