0

当我尝试对我的 JavaScript 游戏进行一些事件处理时,我遇到了一些奇怪的行为。我不是 JavaScript 专家,我觉得我错过了一些重要的东西,但我不知道出了什么问题。

我做了这个EventManager “类”:

function EventManager(events) {

    var _events;

    this.addEventCallback = function(eventName, callback) {
        _events[eventName].push(callback);
    }

    this.fireEvent = function(eventName) {
        for (var i = 0; i < _events[eventName].length; i++) {
            _events[eventName][i]();
        }
    }

    // constructor

    __construct = function(that) {
        _events = [];
        for (key in events) {
            _events[events[key]] = new Array();
        }
    }(this)

}

在我的 GameObject类中,我像这样使用 EventManager:

function GameObject() {

    // define event ids
    var _events = {
        MOVE_START: 0,
        MOVE_STOP: 1
    }

    var _eventManager;

    // how i fire the event:

    this.moveLeft = function() {
        if (!_isMoving()) {
                _eventManager.fireEvent(_events.MOVE_START);
                _velocity = new Vector(-1, 0);
        }
    }

    // event registration "interface"

    this.onMoveStart = function(fn) {
        _eventManager.addEventCallback(_events.MOVE_START, fn);
    }

    this.onMoveStop = function(fn) {
        _eventManager.addEventCallback(_events.MOVE_STOP, fn);
    }

    // constructor

    __construct = function(that) {
        _eventManager = new EventManager(_events);
    }(this);

}

然后我测试一下:

    for (var i = 0; i < _gameObjects.length; i++) {
        console.log("event handler to object number " + i);
        _gameObjects[i].onMoveStart(function() {
            console.log("object number " + i + " started moving");
        });
    }

当我移动第一个对象时,我希望输出是“对象编号 0 开始移动”,而当我移动第二个对象时输出是“对象编号 1 开始移动”,依此类推。

输出总是:"object number 3 started moving"。无论我移动哪个对象,它总是说对象编号 3。对我来说最奇怪的部分是,我的_gameObjects-Array 中只有 3 个对象,所以我至少希望它会说“第 2 个对象开始移动”。

我试过这样做:

    for (var i = 0; i < _gameObjects.length; i++) {
        var num = i;
        console.log("event handler to object number " + num);
        _gameObjects[i].onMoveStart(function() {
            console.log("object number " + num + " started moving");
        });
    }

然后,她的输出总是:“object number 2 started moving”

我确信这些对象并不完全相同,因为我可以移动我想要的对象。

非常感谢你的帮助!

4

1 回答 1

1

您的问题的答案是“是”,即您确实错过了一些关于 JS 匿名函数中的变量范围的内容。我推荐阅读 Javascript Closures for Dummies,这里全文引用了一篇文章:JavaScript 闭包如何工作?.

要使您的测试代码正常工作,您可以这样做:

function notifyStart(i) {
    return function() {
        console.log("object number " + i + " started moving");
    }
}

for (var i = 0; i < _gameObjects.length; i++) {
    _gameObjects[i].onMoveStart( notifyStart(i) );
}
于 2013-04-19T12:44:14.300 回答