声明后立即未定义的变量

Undefined variable immediately after declaring it?

本文关键字:变量 未定义 声明      更新时间:2023-09-26

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

main.js:39 未捕获的引用错误:未定义游戏

在这种情况下,该行是;

game.context.beginPath();

但是,直到 init 函数调用 game.balls.push(/../) 时才调用此行;此时我还没有宣布"游戏",还是我错过了什么?

这是我的代码(对长度表示歉意,希望大部分可以忽略):

/*
 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));
    });
}

更新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()实例的引用。

由于您在 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函数。这意味着无法在此函数之外访问它。对此有很多解决方法。你可以使游戏成为全局变量,或将其传递给Ball构造函数。

另一种可能的解决方案是拥有一个全局命名空间来跟踪这些重要对象。

var SomeNamespace= {};
SomeNamespace.game= new Game();

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

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

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