Каков объем переменной JavaScript, объявленной в для () цикл?

Проверьте следующий отрывок HTML/кода JavaScript:

<html>
<head>
<script type="text/javascript">
var alerts = [];
for(var i = 0; i < 3; i++) {
    alerts.push(function() { document.write(i + ', '); });
}

for (var j = 0; j < 3; j++) {
    (alerts[j])();
}

for (var i = 0; i < 3; i++) {
    (alerts[i])();
}
</script>
</head><body></body></html>

Это производит:

3, 3, 3, 0, 1, 2

который не является тем, что я ожидал - я ожидал вывод 0, 1, 2, 0, 1, 2,

Я (неправильно) предположил, что анонимная функция, продвигаемая в массив, будет вести себя как закрытие, получая значение i это присвоено, когда функция создается - но это на самом деле появляется это i ведет себя как глобальная переменная.

Может любой объяснять, что происходит с объемом i в этом примере кода, и почему анонимная функция не получает свое значение?

10
задан Dylan Beattie 28 April 2010 в 21:57
поделиться

2 ответа

В Javasript единственная "интересная" граница лексической области видимости - это тело функции. Все, что объявлено где угодно в функции (ну, где угодно, кроме другой вложенной функции!), Находится в той же области видимости. Есть также некоторые странности в том, как интерпретируются объявления.

Ваша анонимная функция действует как закрытие, но каждая созданная функция будет иметь одно и то же «i». Уловка, которую я использую, состоит в том, чтобы добавить еще один уровень функций:

for (var i = 0; i < whatever; i++) {
  (function(idaho) {
    whatever(function() { alert("my own private " + idaho); });
  })(i);
}

Надеюсь, в какой-то момент все браузеры будут поддерживать новый оператор let, который является более коротким и менее странным способом сделать в основном то же самое.

6
ответ дан 3 December 2019 в 23:12
поделиться

Область видимости - это функция, в которой определена переменная (за исключением того, что ее нет, поэтому она глобальная).

Анонимная функция, которую вы передаете, обращается к переменной, определенной в области родительской функции (опять же глобальной).

Вам нужно фактическое закрытие.

alerts.push(
    function (foo) { 
        return function() { 
            document.write(foo + ', ');

        }
    }(i)
);
8
ответ дан 3 December 2019 в 23:12
поделиться
Другие вопросы по тегам:

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