объем переменных в функциях обратного вызова JavaScript

Я ожидал, что код ниже предупредит "0" и "1", но он предупреждает "2" дважды. Я не понимаю причины. Не знайте, является ли это проблема jQuery. Кроме того, помогите мне отредактировать заголовок и теги этого сообщения, если они неточны.

<html>
    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type="text/javascript">
            $(function() {
                for (var i=0; i<2; i++) {
                    $.get('http://www.google.com/', function() {
                        alert(i);
                    });
                }
            });
        </script>
    </head>
    <body>
    </body>
</html>
19
задан gylaz 21 January 2014 в 03:03
поделиться

4 ответа

Вы разделяете единственную переменную i между всеми обратными вызовами.

Поскольку замыкания в Javascript захватывают переменные по ссылке, обратные вызовы всегда будут использовать текущее значение i. Поэтому, когда jQuery вызовет обратные вызовы после выполнения цикла, i всегда будет 2.

Вам нужно ссылаться на i как на параметр отдельной функции.

Например:

function sendRequest(i) {
    $.get('http://www.google.com/', function() {
        alert(i);
    });
}

for (var i = 0; i < 2; i++) {
    sendRequest(i);
}

Таким образом, каждый обратный вызов будет иметь отдельное закрытие с отдельным параметром i.

38
ответ дан 30 November 2019 в 02:29
поделиться

Здесь происходит то, что ваш запрос AJAX $. Get завершается после завершения цикла. Из-за этого i в конечном итоге становится последней переменной, которая устанавливается после завершения итераций, равной 2. Это просто странная ошибка JavaScript, не имеющая ничего общего с jQuery.

Единственное, что вы можете сделать, - это поставить эти вызовы в очередь асинхронно, чтобы итерация останавливалась до завершения текущего запроса AJAX. Если вы не хотите этого делать, вы можете зафиксировать переменную i в закрытии функции на каждой итерации.

Примерно так:

for ( var i = 0; i < 2; i++ )
    (function(iter){
        $.get('http://www.google.com/', function(){
            alert( iter );
        });
    })(i); // Capture i
1
ответ дан 30 November 2019 в 02:29
поделиться

Похоже, что вы создали закрытие внутри своего цикла. В Справочнике разработчиков Mozilla есть хороший раздел об этом.

0
ответ дан 30 November 2019 в 02:29
поделиться

Альтернатива ответу Слакс

$(function() {
    for (var i=0; i<2; i++) {
        $.get('http://www.google.com/', function(i) {
            return function() { alert(i); }
        }(i));
    }
});
13
ответ дан 30 November 2019 в 02:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: