Javascript Array addEventListener - PullRequest
       20

Javascript Array addEventListener

3 голосов
/ 19 июня 2011

Интерактивная карта с кнопками в форме состояний, каждая кнопка имеет аббревиатуру состояния в качестве идентификатора, при нажатии кнопки / состояния я хочу запустить функцию «stateSelect» и отправить аббревиатуру состояний вместе с ней, чтобы я зналчто было нажатоПочему следующее не работает?

    var stateList = new Array("AK","AL","AR","AS","AZ","CA","CO","CT","DC","DE","FL","GA","GU","HI","IA","ID",
    "IL","IN","KS","KY","LA","MA","MD","ME","MH","MI","MN","MO","MS","MT","NC","ND","NE","NH","NJ","NM","NV","NY",
    "OH","OK","OR","PA","PR","PW","RI","SC","SD","TN","TX","UT","VA","VI","VT","WA","WI","WV","WY");

    for (var i = 0; i < stateList.length; i++) {
        document.getElementById(stateList[i]).addEventListener('mousedown', function() {stateSelect(stateList[i])}, false);
    }

Я, очевидно, хочу избежать 50 строк кода, но я не уверен, почему этот простой цикл не работает.

Ответы [ 2 ]

5 голосов
/ 19 июня 2011

Потому что, когда обработчик запускается, он ищет значение i, где бы оно ни было после завершения цикла.

Вам необходимо указать переменную i в функции:

function listenerForI( i ) {
    document.getElementById(stateList[i]).addEventListener('mousedown', function() {stateSelect(stateList[i])}, false);
}
for (var i = 0; i < stateList.length; i++) {
    listenerForI( i );
}

Теперь i, на который ссылается обработчик, будет параметром вызываемой функции listenerForI.Таким образом, i будет ссылаться на значение, переданное из цикла for.

1 голос
/ 19 июня 2011

У вас есть проблема с областью видимости. Javascript не имеет блочной области видимости; это функционально ограничено. По сути, вы должны создавать новую функцию всякий раз, когда хотите создать новую переменную в цикле.

Самый элегантный способ сделать это так:

stateList.map(function(abbrev){
    $(abbrev).mousedown(function(){stateSelect(abbrev)});
});

Если вы не используете jQuery, просто замените $(abbrev).mousedown на document.getElementById(abbrev).addEventListener.

(Просто для того, чтобы предупредить людей, которые идут «карта не стандартная»; она есть в стандартном пятом издании ECMA-262 на языке javascript, который поддерживается всеми поставщиками браузеров. $.map.)

Вот как можно это сделать, используя цикл for; это немного уродливее, но демонстрирует необходимость создания новых замыканий с помощью функций:

for(var i=0; i<stateList.length; i++)
    (function(i){
        $(stateList[i]).mousedown(...);
    })(i);

Как я уже сказал, немного страшнее, чем необходимо; Вы также можете сделать это немного менее уродливо, но в основном это то же самое:

function createListener(abbrev) {
    $(abbrev).mousedown(...);
}
for(var i=0; i<stateList.length; i++)
    createListener(stateList[i]);
...