1

我正在尝试使用规则对象添加事件侦听器,如下所示

keyMap = [
    {name: "Up", type: "keydown", code: 87, action: function(){alert("up")}},
    {name: "Down", type: "keydown", code: 83, action: function(){alert("down")}},
    {name: "Left", type: "keydown", code: 65, action: function(){alert("left")}},
    {name: "Right", type: "keydown", code: 68, action: function(){alert("right")}}
]

for(var keyAct of keyMap){
    if( typeof keyAct.action === "function" ){
         document.addEventListener(keyAct.type, function(e){
            if(e.keyCode === keyAct.code){
                keyAct.action(e);
            }
         });
    }
}

然后 w/a/s/d 按所有警报“正确”。我重写了for这样的部分:

for(var keyAct of keyMap){
    (function(keyAct){
        if( typeof keyAct.action === "function" ){
             document.addEventListener(keyAct.type, function(e){
                if(e.keyCode === keyAct.code){
                    keyAct.action(e);
                }
             });
        }
    })(keyAct);
}

它有效,但这是唯一的方法吗?我可以做得更优雅吗?我的意思是,这看起来很奇怪。

4

2 回答 2

1

创建另一个函数来绑定事件,试试这个:

for(var i = 0, len = keyMap.length; i < len; ++i) {
    if( typeof keyMap[i].action === "function" ) {
        binder(keyMap[i]);
    }
}

function binder(keyAct) {
    document.addEventListener(keyAct.type, function(e) {
        if(e.keyCode === keyAct.code) {
            keyAct.action(e);
        }
    });
}
于 2013-09-18T10:24:57.107 回答
0

我总是将这样的构建器函数分开,以避免不必要地重新创建构建器函数并且为了清楚起见:

for(var keyAct of keyMap){
    if( typeof keyAct.action === "function" ){
         document.addEventListener(keyAct.type, buildHandler(keyAct));
    }
}

// Elsewhere
function buildHandler(keyAct){
    return function(e) {
        if(e.keyCode === keyAct.code){
            keyAct.action(e);
        }
    };
}

旁注:for-in循环不是为遍历数组条目而设计的,它们是为遍历对象的可枚举属性而设计的。在数组上使用它们往往会给您带来麻烦(如果您曾经将可枚举的非索引属性直接或通过扩展添加到数组中Array.prototype)。细节:神话与现实for..in

于 2013-09-18T10:23:39.757 回答