0

ループ内の要素にJavaScriptのイベントリスナーを適用したい。イベント名はループ内で可変です。コードを試してみると、最後の addEventListener だけが機能していませんか? 追加したいイベントは、click と mouseenter です。アイテムをクリックすると、発生するのは mouseenter イベントです!

_apply = function(trackEventData, trackEventItem) {

    var tmpData, i, j, eventType, eventAction;

    // get stringified json events
    tmpData = JSON.parse(trackEventData);
    for (i = 0; i < tmpData.length; i++) {
        // for each type in events

        eventType = Events.getEventTypeByKey(tmpData[i].key);
        eventAction = tmpData[i].actions;
        console.log('apply ' + eventType.event);
        // we add the event listener

        trackEventItem.addEventListener(eventType.event, function(e) {
            console.log('eventfired ' + eventType.event);
            e.preventDefault();
            // and for each action we add the function callback
            for (j = 0; j < eventAction.length; j++) {
                Events.getEventActionByKey(eventAction[j].value).action(eventAction[j].options);
            }

        });


    }


};
4

1 に答える 1

2

あなたの問題は閉鎖の1つです。

単純化すると、コードは次のようになります。

var events = ['click', 'mousedown'];
for (var i=0; i<events.length; i++) {
  var a = events[i];
  window.setTimeout(function(){
    console.log(a);
  },0);
}

そこの関数は、外側のスコープで定義された変数をログに記録します。作成された両方の関数 (反復ごとに 1 つ) は、同じ変数を出力します。関数が作成された時点では、変数の値は異なりますが、関数が呼び出されると、変数の値は「mousedown」になるため、両方とも「mousedown」がログに記録されます。

やりたいことは、a各関数に対して変数のローカル バージョンを作成することです。しかし、そこに書いているのはコールバックなので、パラメーターを変更することはできません。解決策は、それを別の関数でラップし、クロージャーを再度使用することです (ただし、今回は適切に):

for (var i=0; i<events.length; i++) {
  var a = events[i];
  window.setTimeout(function(obj){ return function(){
    console.log(obj);
  }}(a),0);
}

ご覧のとおり、to の現在の値を保存する反復ごとにスコープを作成しましたa(objパラメーターとして無名関数に渡すことによって)。実際のハンドラーは、特に反復に対して、そのスコープ内の値を使用します。

デモ: http://jsbin.com/agoDaza/1/edit

于 2013-10-24T14:09:24.493 に答える