Почему теневая переменная оценивается как неопределенная, если она определена вне области видимости? - PullRequest
8 голосов
/ 07 октября 2009

Рассмотрим следующий фрагмент кода:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
        }
        f1();
    </script>
</body>
</html> 

Выход для этого кода: окно предупреждения отображает сообщение «снаружи» область ". Но, если я немного изменить код как:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
            var outside_scope = "inside scope";
        }
        f1();
    </script>
</body>
</html> 

в окне предупреждения отображается сообщение " undefined ". я мог бы иметь понял логику, если он отображает «неопределенный» в обоих случаях. Но это не происходит Отображает «неопределенный» только во втором случае. Почему это?

Заранее спасибо за помощь!

Ответы [ 6 ]

20 голосов
/ 07 октября 2009

Переменные могут быть подъем . Это означает, что независимо от того, где переменная находится внутри функции, она перемещается в верхнюю часть области, в которой она определена.

Например:

var outside_scope = "outside scope";
function f1() {
    alert(outside_scope) ;
    var outside_scope = "inside scope";
}
f1();

Получается в виде:

var outside_scope = "outside scope";
function f1() {
    var outside_scope; // is undefined
    alert(outside_scope) ;
    outside_scope = "inside scope";
}
f1();

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

12 голосов
/ 07 октября 2009

В первом случае ваш код обращается к глобальной переменной "outside_scope", которая была инициализирована как "outside scope".

Javascript имеет область действия уровня функции, поэтому во втором случае он обращается к переменной области действия «outside_scope», но он еще не был инициализирован во время окна предупреждения. Так что отображается неопределенное.

5 голосов
/ 07 октября 2009

JavaScript имеет область действия, а не область блока.

Во втором случае объявление outside_scope поднимается до верха функции (но назначение - нет).

Это отличный пример того, почему код JavaScript легче читать, если вы поместите все объявления переменных вверху функции. Ваш второй пример эквивалентен:

function f1() {
    var outside_scope;
    alert(outside_scope);
    outside_scope = "inside scope";
}

и теперь вы, вероятно, можете понять, почему вы получаете "undefined".

4 голосов
/ 07 октября 2009

Во втором примере локальная переменная существует для всей области действия функции. Неважно, что вы определили его после предупреждения, оно существует для всей функции.

Тем не менее, фактическое назначение происходит только после оповещения, следовательно, "undefined".

1 голос
/ 24 мая 2010

Это связано с тем, что поднял объявления переменных .

По сути, JavaScript разделяет объявление переменной на две , оставляя присвоение, в котором вы сделали объявление, и поднимая фактическое объявление до верхней части функции :

var f1 = function ()  {
   // some code
   var counter = 0;
   // some more code
}

var f2 = function () {
   var counter; // initialized with undefined
   // some code
   counter = 0;
   // some more code
}

Во время выполнения f1() переводится в f2(). Я написал подробное сообщение в блоге об этом здесь . Я надеюсь, что это поможет вам понять, что происходит в вашем коде.

Это также причина, поэтому рекомендуется объявлять переменные в начале функции в JavaScript. Это поможет вам понять, что делает код, когда он выполняется.

1 голос
/ 07 октября 2009

это интересный случай.

в первом примере вы определили «глобальную» переменную. он имеет глобальную область видимости и поэтому доступен для выполнения в любой функции / объекте.

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

Я согласен, что это не самая интуитивная причуда, но она имеет смысл.

...