javascript - TypeScript 中的 KeyListener 和 "this"上下文

标签 javascript typescript

我正在用 TypeScript 编写贪吃蛇游戏,但在定义 KeyListener(用于改变贪吃蛇方向的箭头键)时遇到了问题。

我有一个 4 层架构,关键事件在 Gui 类中处理。这包含 Snake 对象、绘制蛇并处理关键事件。

我尝试了正常的方式,但是在 handleEvt 内部,snake 对象是未定义的。

document.addEventListener("keydown", handleEvt)

所以我尝试了粗箭头方法,但现在函数根本没有被调用。我怀疑关键监听器更改了上下文并且不再在窗口上工作

document.addEventListener("keydown", () => handleEvt)

谁能解释一下这里的问题是什么?将不胜感激!

下面是我的 Gui 类:

/// <reference path="../model/Snake.ts" />
/// <reference path="../model/Direction.ts" />
/// <reference path="../model/Part.ts" />
/// <reference path="../dao/Dao.ts" />
/// <reference path="../service/Service.ts" />
/// <reference path="../model/IPosObject.ts" />

module gui {

    export class Gui {
        snake:model.Snake;
        canvas:HTMLCanvasElement;
        ctx:CanvasRenderingContext2D;
        loop:any;

        lineWidth:number;
        canvasSize:number;
        loopSpeed:number;
        unitLength:number;

        constructor(snake:model.Snake) {
            // init constants
            this.snake = snake;
            this.lineWidth = 3;
            this.canvasSize = 200;
            this.loopSpeed = 1000/60;
            this.unitLength = 5;

            // init canvas
            this.canvas = document.getElementsByTagName("canvas")[0];
            this.canvas.width = this.canvasSize;
            this.canvas.height = this.canvasSize;
            this.ctx = this.canvas.getContext("2d");

            // Attach key event
//            document.addEventListener("keydown", this.handleEvt);
            document.addEventListener("keydown", () => this.handleEvt);

            // activate game loop
            this.loop = setInterval( () => this.gameLoop(), this.loopSpeed );
        }

        handleEvt(e):void {
            var direction:model.Direction;

            if (e) {
                switch (e.which) {
                    case 37:
                        console.log("left");
                        direction = model.Direction.Left;
                        break;
                    case 38:
                        console.log("up");
                        direction = model.Direction.Up;
                        break;
                    case 39:
                        console.log("right");
                        direction = model.Direction.Right;
                        break;
                    case 40:
                        console.log("down");
                        direction = model.Direction.Down;
                        break;
                }

                this.snake.changeDirection(direction);
            }
        }

        gameLoop():void {
            if (this.snake) {
                this.drawSnake();
            }
        }

        drawSnake() {
          // draw parts
        }
    }

}

最佳答案

这个问题有多种解决方案,您可以在 addEventListener 端修复它,方法与您对 setInterval 所做的相同。在 keyDown 监听器中,您没有调用 handleEvt,因此将其更改为 () => this.handleEvt().

另一个可以像上面那样使用它的解决方案是: document.addEventListener("keydown", this.handleEvt);

然后像这样声明 handleEvt:

handleEvt = (e) => {
    var direction:model.Direction;
    ...<snip>
}

或者另一种解决方案: document.addEventListener("keydown", this.handleEvt.bind(this));

如您所见,有不同的解决方案,您可以选择自己喜欢的一种。 this 丢失是因为该函数不是在实例上调用的,这是正常的(但有时会造成混淆)JavaScript 行为。

关于javascript - TypeScript 中的 KeyListener 和 "this"上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29575916/

相关文章:

javascript - 如何在函数执行期间停止函数 - JavaScript

javascript - 如何有条件地使用javascript在网页上的选定单词上显示鼠标悬停工具提示?

javascript - 用于选择单选按钮的 greasemonkey 脚本

reactjs - 网页包 4 : Module parse failed: Unexpected token

javascript - 如何检查 javaScript 中对象数组中是否存在某个值?

javascript - window.onload 和 getelementbyid 返回 null

javascript - 如何将 Material 选择和标签并排放在同一行

angular - 我是否有多个导出常量实例或多次导入时有一个实例?

javascript - Dx数据网格 : Validating multiple edit fields at once

typescript - 将 Typescript 全局变量声明为 "module"类型