Область переменной Javascript внутри цикла
Как мне поддерживать доступ к переменной i
внутри цикла for for ниже? Я пытаюсь учиться, а не просто получить ответ, поэтому немного объяснений будет очень полезно. Спасибо!
var el,
len = statesPolyStrings.length;
for (var i = 0; i < len; i++) {
el = document.getElementById(statesPolyStrings[i]);
google.maps.event.addDomListener(el, 'mouseover', function() {
$("#"+statesPolyStrings[i]).addClass("highlight");
statesPolyObjects[i].setOptions({ strokeWeight: '2' });
});
}
Ответы
Ответ 1
Все ваши обратные вызовы используют одну и ту же переменную i
.
Когда обработчик событий действительно запускается, i
находится после конца массива.
Вам нужно обернуть тело цикла в функцию самозапускания, которая принимает i
в качестве параметра.
Таким образом, каждая итерация получит свою собственную неизменную переменную i
.
Например:
for (var i = 0; i < statesPolyStrings.length; i++) {
(function(i) {
...
})(i);
}
Ответ 2
Трюк с функциями для самостоятельного вызова отлично работает: он создает новую область (возможно, google для "scope в функциях javascript" ) и поэтому обрабатывает i
как другую переменную и доставляет правильное значение функции обратного вызова слушателя событий.
Но вам действительно не нужно снова находить свой элемент с помощью jQuery, поскольку вы уже назначили ему прослушиватель событий, а внутри вашей функции у вас есть ссылка на ваш элемент с this
.
И как вы все равно используете jQuery, тогда легко найти правильный индекс (ваш i
) statesPolyObjects
с помощью $.inArray()
передача идентификатора вашего элемента и массива statesPolyStrings
(при условии, что вы имеете дело с уникальными идентификаторами. Если нет, $("#"+statesPolyStrings[i])
также потерпит неудачу, так как он принимает первое, что он находит).
var el;
for (var i = 0, len = statesPolyStrings.length; i < len; i++) {
el = document.getElementById(statesPolyStrings[i]);
google.maps.event.addDomListener(el, 'mouseover', function(event) {
$(this).addClass("highlight");
statesPolyObjects[$.inArray(this.id, statesPolyStrings)].
setOptions({ strokeWeight: '2' });
});
}
Если вы все еще хотите придерживаться функции самозапускания, вы должны изменить следующую строку:
("#"+statesPolyStrings[i]).addClass("highlight");
к
$(this).addClass("highlight");
Если вы недостаточно знакомы с this
и событиями, которые вы, возможно, захотите прочитать в этой статье:
http://www.sitepoint.com/javascript-this-event-handlers/
Возможно, вы заметили, что я также написал аргумент event
внутри функции анонимного обратного вызова. Попробуйте console.log
это событие, которое вы получите бесплатно с помощью функции обратного вызова прослушивателя событий и изучите все другие вещи, к которым у вас есть доступ. Например, вы можете найти фактический элемент, на который вы нажали, с помощью event.target
(поскольку фактическое наведение мыши могло произойти с дочерним элементом вашего элемента). Итак:
google.maps.event.addDomListener(el, 'mouseover', function(event) {
console.log(event);
...
и откройте консоль вашего браузера, чтобы узнать, какое событие поставляет...
Помните, что google.maps.event.addDomListener
передает что-то другое, чем document.body.addEventListener
, а также разница между браузерами. Например, jQuery.on() также предоставляет некоторые вещи в объекте события, но там вы можете, по крайней мере, рассчитывать на одни и те же данные во всех браузерах.
Ответ 3
for (var i = 0; i < statesPolyStrings.length; i++) {
(function(i){
google.maps.event.addDomListener(document.getElementById(statesPolyStrings[i]), 'mouseover', function() {
$("#"+statesPolyStrings[i]).addClass("highlight");
statesPolyObjects[i].setOptions({ strokeWeight: '2' });
});
})(i)
}