我得到一些奇怪的行为,因为我试图实现一点事件处理到我的javascript游戏。我不是JavaScript专家,我觉得我错过了一些重要的东西,但我不知道哪里出了问题。
我设置了EventManager "class":
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开始移动"。
I tried doing this:
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");
});
}
那么,她的输出总是:"对象2开始移动"。
我确信这些对象并不都是相同的,因为我可以移动我想要的对象。
非常感谢你的帮助!
你的问题的答案是"是",即你确实错过了JS匿名函数中变量作用域的一些东西。我推荐你阅读Javascript闭包入门教程,这篇文章的全文引用在这里:How do 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) );
}