В Javascript функция запускает новую область, но мы должны быть осторожны, чтобы функция вызывалась для создания области, это так? - PullRequest
2 голосов
/ 30 апреля 2010

В Javascript я иногда слишком погружен в идею о том, что функция создает новую область, и иногда я даже думаю, что следующая анонимная функция создаст новую область, когда она определена и назначена для onclick:

<a href="#" id="link1">ha link 1</a>
<a href="#" id="link2">ha link 2</a>
<a href="#" id="link3">ha link 3</a>
<a href="#" id="link4">ha link 4</a>
<a href="#" id="link5">ha link 5</a>


<script type="text/javascript">

    for (i = 1; i <= 5; i++) {

        document.getElementById('link' + i).onclick = function() { var x = i; alert(x); return false; }
    }

</script>

но на самом деле анонимная функция создаст новую область видимости, верно, но ТОЛЬКО когда она вызывается, так ли это? Таким образом, x внутри анонимной функции не создается, новая область не создается. Когда функция была позже вызвана, новая область в порядке, но i находится во внешней области, и x получает свое значение, и в любом случае это все 6.

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

<a href="#" id="link1">ha link 1</a>
<a href="#" id="link2">ha link 2</a>
<a href="#" id="link3">ha link 3</a>
<a href="#" id="link4">ha link 4</a>
<a href="#" id="link5">ha link 5</a>


<script type="text/javascript">

    for (i = 1; i <= 5; i++) {

        (function() {
            var x = i;
            document.getElementById('link' + i).onclick = function() { alert(x); return false; }
        })();  // invoking it now!
    }

</script>

Если мы уберем var перед x, то это глобальная x, поэтому в новой области видимости локальная переменная x не создается, и, следовательно, нажав на ссылки, вы получите все тот же номер, который является значением глобального x.

Обновление: вопрос в том, что мы должны быть осторожны при анализе кода, чтобы функция не создавала область видимости, когда она просто определена и назначена. Это должно быть вызвано. Это так?

Ответы [ 3 ]

2 голосов
/ 30 апреля 2010

Вы правы, но вы также путаете себя. Вместо того, чтобы думать о функциях, как о «создании новой области видимости», лучше понять, что на самом деле происходит. Javascript интерпретирует переменную, просматривая цепочку областей видимости. Если переменная не присутствует в области действия функции, она переместится в область действия включающего уровня в случае замыкания. Эта часть происходит во время интерпретации переменной. Сама область видимости создается, когда функция есть, но в том случае, если вы запутались, ничего не «захватывается» в область действия в то время. Это просто расширение цепочки областей видимости .

Именно поэтому вставка замыканий в циклы является такой "ошибкой" в программировании на javascript - вы вправе вставить автоматически выполняющуюся анонимную функцию, если хотите захватить значение i во время объявления функции , Люди склонны думать (особенно исходя из процедурных языков), что внешняя область заморозилась и все текущие значения передаются в новую область функции, и это не так.

1 голос
/ 30 апреля 2010

Область действия функции устанавливается при создании объекта функции , например:

var fn;
// augment scope chain:
with ({foo: "bar"}) {
  fn = function () { // create function
    return foo;
  };
}​​
// restored scope chain
fn(); // "bar"

В приведенном выше примере функция создается внутри блока with, там текущая область расширяется, чтобы представить объект со свойством foo в цепочку областей действия.

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

В тот момент, когда функция автоматически вызывается при каждой итерации цикла, значение i фиксируется в этой области в переменной x, затем в этой области создается функция обработчика onclick, и она сможет решить это.

0 голосов
/ 30 апреля 2010

Я не понимаю вашего вопроса, но я не вижу в этом ничего странного или неправильного.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...