类变量在JavaScript中返回undefined

时间:2013-09-26 16:23:04

标签: javascript class variables

我是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背景我觉得这个行为很奇怪。我该如何正确设置我的类变量?

4 个答案:

答案 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. 将您的功能绑定到您希望它位于Bind JS v1.8上的对象(看到你正在使用不应该成为问题的画布。
  2. 使用其上下文显式调用方法。 (见上文)

答案 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);
  }
}