我是JavaScript的新手。因此这个问题有点令人困惑。我试图简单地定义一个计数器并在类方法中增加它,但它的行为不像我期望的那样。具体来说,console.log(this.tick_count);
打印undefined
。
JavaScript的:
function Game() {
this.fps = 50;
this.ticks = 3;
this.current_time = (new Date).getTime();
this.draw_object = document.getElementById('game_canvas').getContext('2d');
this.tick_count = 0;
}
Game.prototype.update = function (time) {
this.current_time = time;
}
Game.prototype.draw = function () {
this.draw_object.fillRect(10, 10, 55, 50);
}
Game.prototype.run = function () {
self.setInterval(this.tick, 1000 / (this.fps * this.tick));
}
Game.prototype.tick = function () {
this.tick_count++;
console.log(this.tick_count);
}
function start_game() {
var game_object = new Game();
game_object.run();
}
HTML:
<body onload="start_game()">
<canvas id="game_canvas" width="1024" height="1024"></canvas>
</body>
来自Python背景我觉得这个行为很奇怪。我该如何正确设置我的类变量?
答案 0 :(得分:7)
这就是发生的事情。
基本上,tick
函数不再在game_object
对象的上下文中运行。这可能听起来很奇怪来自Python背景,但基本上this
对象被设置为其他东西。
那它设定的是什么?很容易,window
对象,我们怎么知道这个?因为setInterval
的上下文是window
对象。
移动示例,因为代码无法在
下正确格式化绑定示例
setInterval(this.tick.bind(this), 1000 / (this.fps * this.tick)); //Native (JS v1.8+)
$.proxy(this.tick, this); //jQuery
_.bind(this.tick, this); //underscore / lodash
明确的上下文示例
Game.prototype.run = function () {
var _this = this;
setInterval(function() {
//So what is this at the moment? window.
//Luckily we have a reference to the old this.
_this.tick();
}, 1000 / (this.fps * this.tick));
};
你可以绕过这两种方式。
答案 1 :(得分:3)
尝试
setInterval(this.tick.bind(this), 1000 / (this.fps * this.tick));
// without "self"
感谢PSL和TJ Crowder
答案 2 :(得分:2)
这将有效:
setInterval(this.tick.bind(this), 1000 / (this.fps * this.tick));
就像这样:
var self = this;
setInterval(function () {
self.tick();
}, 1000 / (this.fps * this.tick));
答案 3 :(得分:0)
尽管已经回答了这个问题,但我认为您需要了解this
所指的内容。有关详细信息,请参阅this answer。
如果您想使用闭包而不是绑定,则可以通过调用返回函数的函数(在当前运行的函数之外)来限制范围。这样可以最大限度地减少闭包可用的变量数量。听起来很复杂,但只需稍微调整一下代码就可以了:
Game.prototype.run = function () {
//best not to define a closure here because the next variable
//will be available to it and won't go out of scope when run
//is finished
var memoryEatingVar=new Array(1000000).join("hello world");;
//note that this.tick(this) is not passing this.tick, it's invoking
//it and the return value of this.tick is used as the callback
//for the interval
setInterval(this.tick(this), 1000 / (this.fps * this.tick));
}
//note the "me" variable, because the outer function Game.prototype.tick
//returns a inner function (=closure) the me variable is available in
//the inner function even after the outer function is finished
Game.prototype.tick = function (me) {//function returning a function
return function(){
me.tick_count++;
console.log(me.tick_count);
}
}