ThunderCat
@ThunderCat
{PHP, MySql, HTML, JS, CSS} developer

JQ странно присваивает слушатели в цикле или я туплю?

Есть группа чекбоксов, на каждый нужно повесить листенер с функцией скрытия/показа элемента. Таких групп много, по этому возникла идея навесить все одним махом, в цикле при window.onload, тупо проименовав псевдоклассы c окончанием от 1 до n( s1, sport1, s2, sport2...). И понеслась...
for(i=1; i<23; i++){
        $(".s"+i).on("ifUnchecked", function () {
            ctoggler("sport"+i, 0);
            alert(i); //алерт выдает 23 на всех элементах
            });
            $(".s"+i).on("ifChecked", function () {
            ctoggler("sport"+i, 1);
            });
    };

ctoggler() принимает имя класса переключаемого элемента и состояние вкл/выкл (1/0).
По завершении цикла ВСЕМ элементам s1-22 переключение элемента с номером 23.
ИМХО косяк с передачей i в замыкание. Как я понимаю(в жс я не профи), оно берет значение i из текущего состояния на момент вызова евента, которое как раз 23.
Вопрос: Как "зафиксировать" i для текущего евента?
  • Вопрос задан
  • 276 просмотров
Решения вопроса 1
@Sayonji
Было:
$(".s"+i).on("ifUnchecked", function () {
    ctoggler("sport"+i, 0);
    alert(i);
});
$(".s"+i).on("ifChecked", function () {
    ctoggler("sport"+i, 1);
});

Стало:
$(".s"+i).on("ifUnchecked", function (i) { // <--- аргумент
    ctoggler("sport"+i, 0);
    alert(i);
}.bind(null, i)); // <--- зафиксировали
$(".s"+i).on("ifChecked", function (i) { // <--- аргумент
    ctoggler("sport"+i, 1);
}.bind(null, i)); // <--- зафиксировали

Альтернатива 1, так делают обычно:
(function(i) { // <--- аргумент
    $(".s"+i).on("ifUnchecked", function () {
        ctoggler("sport"+i, 0);
        alert(i);
    });
    $(".s"+i).on("ifChecked", function () {
        ctoggler("sport"+i, 1);
    });
}) (i) // <---- зафиксировали

Альтернатива 2, современный javascript:
for(let i=1; i<23; i++){
    // Код как у вас, let создается в каждой итерации цикла заново,
    // и замыкания работают как надо.
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@abberati
frontend-разработчик
Ответ написан
Комментировать
Stalker_RED
@Stalker_RED
Еще круче было бы не плодить 23 одинаковых листенера а перевесить его на родительский элемент.
$('myForm').on('ifChecked', '.someClassname', function(){
  console.log(this)
})
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы