声明后立即未定义的变量?

Undefined variable immediately after declaring it?

我正在使用 var/function 类 在 javascript 中创建一个游戏循环(需要一个更好的词)。但是,我有一个奇怪的错误,其中 javascript 声明变量在声明后立即未定义...

main.js:39 Uncaught ReferenceError: game is not defined

在这种情况下,该行是;

game.context.beginPath();

但是,直到 init 函数调用 game.balls.push(/../) 时才调用此行;到此为止我还没有声明 'game' 吗?还是我遗漏了什么?

这是我的代码(抱歉篇幅太长,希望大部分内容可以忽略):

/*
 Keep This: #217398
 */

var Game = function () {
    this.canvas = document.getElementById('canvas');
    this.context = this.canvas.getContext('2d');

    this.balls = [];

    var that = this;

    this.start = function () {
        requestAnimationFrame(that.update);
    };
    this.update = function () {
        that.draw();
        requestAnimationFrame(that.update);
    };
    this.draw = function () {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

        for(var x = 0; x < this.balls.length; x++){
            this.balls[x].draw();
        }
    };

    this.start();
};

var Ball = function (x, y) {
    this.x = x;
    this.y = y;
    this.dx = 2;
    this.dy = 2;
    this.ballRadius = 10;

    this.draw = function(){
        game.context.beginPath();
        game.context.arc(this.x, this.y, this.ballRadius, 0, Math.PI*2);
        game.context.fillStyle = 'black';
        game.context.fill();
        game.context.closePath();

        this.x += this.dx;
        this.y += this.dy;

        if(this.x + this.dx > game.canvas.width - this.ballRadius || this.x + this.dx < this.ballRadius)
            this.dx = -this.dx;
        if(this.y + this.dy > game.canvas.height - this.ballRadius || this.y + this.dy < this.ballRadius)
            this.dy = -this.dy;
    };
};

function init(){
    var game = new Game();

    game.canvas.addEventListener('click', function(){
        game.balls.push(new Ball(100, 100));
    });
}

因为您在 init 函数中使用 var 关键字声明了 game 变量,它的作用域将仅限于 init 函数(并且对其他函数不可用) init).

中未嵌套的函数
function init(){
    var game = new Game(); // will be scoped to init

    game.canvas.addEventListener('click', function(){
        game.balls.push(new Ball(100, 100));
    });
}

因此,一种选择是在 init 之外声明 game 以扩大其范围,或者您可以将其声明为 Ball.

的实例变量

变量 game 的作用域为创建它的 init 函数。这意味着不能在此函数之外访问它。有很多解决方法。您可以将 game 设为全局变量,或将其传递给 Ball 构造函数。

另一种可能的解决方案是使用全局名称空间来跟踪这些重要对象。

var SomeNamespace= {};

SomeNamespace.game= new Game();

我个人喜欢做的是运行我在闭包中的简单游戏。

(function(){

    var game = new Game();

    var ball = new Ball(); // Ball now has access to game.
})()

旁注,您可以通过省略 var 关键字在函数内创建全局范围的变量,但它被认为是一种不好的做法。

更新 Ball() 以便您可以显式传递对 Game() 实例的引用:

var Ball = function (game, x, y) {
    this.x = x;
    this.y = y;

    // etc
};

然后:

function init(){
    var game = new Game();

    game.canvas.addEventListener('click', function(){
        game.balls.push(new Ball(game, 100, 100));
    });
}

现在 Ball() 代码可以访问对您创建的 Game() 实例的引用。