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

时间:2016-03-09 14:54:26

标签: javascript html variables canvas undefined

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

  

main.js:39未捕获的ReferenceError:游戏未定义

在这种情况下,该行是;

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

3 个答案:

答案 0 :(得分:2)

由于您使用game函数中的var关键字声明了init变量,因此它将作用于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的实例变量。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

变量game的范围限定为创建它的init函数。这意味着无法在此功能之外访问它。有很多工作要做。您可以将游戏设为全局变量,或将其传递给Ball构造函数。

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

var SomeNamespace= {};

SomeNamespace.game= new Game();

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

(function(){

    var game = new Game();

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

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