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);
            }
         });
    }
}

次に、警告されたすべての「右」を押します。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

Create another function to binding events, try this:

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 に答える