Javascript变量超出范围/ null?

时间:2014-04-20 14:56:22

标签: javascript scope

我正在用JavaScript编写一个简单的游戏。我使用的单个JS文件变得一团糟。所以我将它重构为几个类。但是我遇到了一些问题,一些变量变成'空'。

在重绘函数中,“this.ctx”变量为null。我不明白为什么它是null ...在launchGame方法中它正确初始化。

var Game = {
    username : "",
    password : "",
    state : "login",

    interactables : [],
    interactablesOffset : 0,
    c : document.getElementById('gameCanvas'),
    ctx : null,

    usernameInput : "", passwordInput : "", loginBtn : "", loginBtnText : "Login",

    //Initialises handlers and launches the game cycle
    launchGame : function () {
        //Initialize
        this.c.addEventListener("click", this.handleClick, false);
        this.ctx = this.c.getContext('2d');

        setInterval(gameInstance.redraw, 300);
    },

    //Redraws the game every 300 ms
    redraw: function () {
        this.interactablesOffset = 0;
        var user = this.usernameInput != null ? this.usernameInput.value() : "";
        var pw = this.passwordInput != null ? this.passwordInput.value() : "";
        **this.ctx.clearRect(0, 0, 800, 800);//this.ctx is null**
        switch (state) {
            case "login":
                displayLoginMenu(user, pw);
                break;
        }
    },

    //Displays the login menu
    displayLoginMenu : function (_username, _password) {
        ctx.font = "bold 14px sans-serif";
        ctx.fillText("Username:", 5, 70);
        usernameInput = new CanvasInput({ canvas: document.getElementById('gameCanvas'), x: 100, y: 50, value: _username });

        ctx.font = "bold 14px sans-serif";
        ctx.fillText("Password:", 5, 120);
        passwordInput = new CanvasInput({ canvas: document.getElementById('gameCanvas'), x: 100, y: 100, value: _password });

        loginBtn = Object.create(BaseButton);
        loginBtn.x = 100;
        loginBtn.y = 150;
        loginBtn.width = 162;
        loginBtn.height = 25;
        this.addIteractable(obj);

        this.paintInteractables();
    },

    //Paints the interactables to the screen
    paintInteractables : function () {
        for(var i = 0; i < interactables.length; i++)    {
            var obj = interactables[i];
            if(obj !=null)
                obj.paint();
        }
    },
    //Adds an interactable component to the screen
    addIteractable : function addIteractable(obj) {
        interactables[interactablesOffset] = obj;
        interactablesOffset++;
    },

    //Handles clicks on game
    handleClick : function (e) {
        console.log('click: ' + e.offsetX + '/' + e.offsetY);
        for (var i = 0; i < interactables.length; i++) {
            var element = interactables[i];
            if (e.offsetX >= element.x && e.offsetX <= element.x + element.w
                && e.offsetY >= element.y && e.offsetY <= element.y + element.h) {
                console.log("clickBtn");
                interactables[i].pressed();
            }
        }
    }

}

var gameInstance = Object.create(Game);
gameInstance.launchGame();

1 个答案:

答案 0 :(得分:2)

您在此代码中丢失了上下文:

setInterval(gameInstance.redraw, 300);

所以gameInstance.redraw将在全局对象上下文(window)中调用。这意味着它内部的this将指向不是游戏实例而是指向窗口对象。

要解决此问题,您可以:

launchGame : function () {
    //Initialize
    this.c.addEventListener("click", this.handleClick, false);
    this.ctx = this.c.getContext('2d');

    var self = this;
    setInterval(function() {
        self.redraw();
    }, 300);
},

setInterval(this.redraw.bind(this), 300);