JavaScript: проблема с циклом

У меня есть 3 .a и функция, которая должна предупреждать число [0, 1 или 2], которому принадлежит .a, когда оно mouseover-ed:

​function a(){
    for(var c=0; c<3; c++){
        alert(c);
        $('.a:eq('+c+')').mouseover(function(){alert(c)});       
    }

}

Когда я его выполняю, первый alert(c) запускается три раза, а сообщение "0", "1" , "2" соответственно, как и ожидалось.

Однако, когда mouseover .a, независимо от того, что это за .a, выводится предупреждение "3".

http://jsfiddle.net/f6tQn/

Я был бы признателен, если бы кто-нибудь мог объяснить, почему это происходит, и предоставить решение.


person Community    schedule 21.05.2012    source источник
comment
возможный дубликат jQuery для динамического значения цикла   -  person DCoder    schedule 21.05.2012
comment
возможный дубликат замыканий в цикле for   -  person kevingessner    schedule 21.05.2012


Ответы (4)


Это происходит потому, что каждая из ваших mouseover функций использует одно и то же значение c, которое равно 3, когда цикл завершен.

Вам нужно сделать закрытие, чтобы «захватить» значение c для каждой итерации.

function a(){
    for(var c=0; c<3; c++){
        alert(c);
        var func = function(c){
            return function(){ // closes around the current value of "c"
                alert(c);
            };
        };
        $('.a:eq('+c+')').mouseover(func(c));       
    }
}

ДЕМО: http://jsfiddle.net/vDbu3/

person Rocket Hazmat    schedule 21.05.2012

Потому что с=3.

Ваш цикл добавляет 1 к C каждый раз, когда он выполняется, C по-прежнему равно 3 после запуска кода, что дает вашим оповещениям значение C, которое равно 3.

Ваш пример можно полностью переписать и упростить как

$('.a').mouseover(function(){
    alert($(this).index());
});

это создаст предупреждение для всех элементов с классом a и укажет их позицию в массиве, который генерирует $('.a').

Кстати: ошибки JSLint при помещении функций в цикл, если вы хотите, чтобы JSLint был счастлив, проверьте этот вопрос

person JKirchartz    schedule 21.05.2012

Вы попадаете в ловушку переменных области действия в javascript. Это большая ошибка javascript.

Вам нужно создать функцию, которая делает то, что вы хотите, чтобы тело вашего цикла for делало и принимает c в качестве параметра.

person MushinNoShin    schedule 21.05.2012

C привязан к тому же физическому местоположению в памяти, поэтому, когда вы запускаете предупреждение с помощью указателя мыши, оно извлекается из последнего установленного значения, равного 3.

На самом деле вы создаете «замыкание» над переменной c, если хотите глубже прочитать эту тему.

Попробуй это

function a(){
    for(var c=0; c<3; c++){
        alert(c);
        (function(a){
           $('.a:eq('+a+')').mouseover(function(){alert(a)});
        })(c);      
    }

}
person Robert Beuligmann    schedule 21.05.2012
comment
Вам нужно было () около function(a){...}(c). Я исправил это для тебя. - person Rocket Hazmat; 21.05.2012