Вопрос

При запуске следующего блока кода FF и Chrome выводят typeof(hiya) = string в то время как вывод IE7 / 8 typeof(hiya) = undefined.

<html>
    <body>
        <script type="text/javascript">
            window.hiya = 'hiya';
        </script>
        <script type="text/javascript">
            if( false ) {
                var hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>

Каждое из следующих действий устраняет проблему:

  • Объединяя все в единое целое <script> блок.
  • Удаление if блок.
  • Переименование var hiya = 1 Для var hiya2 = 1.
  • Переименование var hiya = 1 Для window.hiya = 1.
  • Переименование var hiya = 1 Для hiya = 1.

Что происходит? Есть ли ошибка при определении области видимости в IE?

Это было полезно?

Решение

Т.е. глупо, это не признает, что window.varName а также var varName Доступ к той же переменной в некоторых случаях.

Когда встречается новый тег сценария, сначала инициализирует все переменные, объявленные с var. Он не запускает оператор var (часть, которая инициализирует его на «Hiya»). Это просто инициализирует его до неопределенного. Это не сделает этого, если он ранее объявлен с VAR, хотя.

Если ваш код был в одном теге скрипта, эта ошибка не произойдет. Кроме того, если первая декларация Hiya была сделана с var, эта ошибка также не произойдет.

В частности, во втором теге сценариев, то есть сначала ищет заявления VAR, он находит var var hiya = 1; Затем он говорит, что Hiya ранее не инициализировалась с операторами VAR ранее (то есть глупыми, другие браузеры распознают это окно. Hiiya делает то же самое) и инициализирует Hiya, перезаписи окно. Hiiya перед выполнением любого кода.

Возможные решения:

  • Держите свой код в том же теге сценария
  • Не инициализируйте переменные с Windows.hiya
  • Если вы не контролируете один из скриптов, убедитесь, что скрипт, который использует VAR, поставляется на первом месте

Последняя записка, чтобы уточнить, какие анализаторы JS делают с вашим кодом. Когда парсер JS видит ваш код, он преобразует его в следующее:

<html>
    <body>
        <script type="text/javascript">
            window.hiya = 'hiya';
        </script>
        <script type="text/javascript">
            // IE is dumb, it doesn't recognize that hiya is already 
            // defined as window.hiya, so it's initialized to undefined here
            var hiya;
            if( false ) {
                hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>

Поэтому, если вы поместите все в один тег скрипта, это то, что код будет (после того, как двигатель JS переместил операторы VAR в верхнюю часть), чтобы вы могли видеть, что IE не может испортить его, так как window.hiya Назначение было бы после того, как VAR, который был перемещен на вершину.

<html>
    <body>
        <script type="text/javascript">
            var hiya;
            window.hiya = 'hiya';
            if( false ) {
                hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>

Другие советы

Основную проблему можно увидеть здесь http://jsfiddle.net/Raynos/UxrVQ/ Мне еще предстоит выяснить, почему IE перезаписывает window.привет без проверки.

[Править]

Из спецификации.Страница 38:

Для каждой переменной Declaration или Переменной Declaration в коде, создайте свойство переменной объект, имя которого является идентификатором в переменной Declaration или переменной Declarationnoin, значение которого не определено и атрибуты которого определяются типом кода.Если свойство объекта variable с именем объявленной переменной уже существует, значение свойства и его атрибуты не изменяются.

Возможным объяснением может быть то, что в глобальном масштабе IE проводит различие между window объект и variable object для глобальной области видимости при объявлении переменных.В качестве альтернативы установка свойства на window объект напрямую может не устанавливать одно и то же свойство на variable объект.Если вы сможете найти официальную спецификацию JScript или у вас есть исходный код IE, тогда мы сможем точно выяснить, в чем заключается эта особенность.

[/Править]

Спасибо @TimDown и @JuanMendes, указывающим, что это проблема с тем, является ли запись свойства в объект window объявлением переменной.

Проблема:

объявление переменной перемещается в верхнюю часть блока.Даже если код мертв.В IE по какой-то причине он объявляет hiya как локальную переменную, даже если она использует свойство с тем же именем, хранящееся в window.

Объяснение:

Что происходит, так это то, что вы объявляете переменную с именем hiya.Оператор var автоматически удаляется в верхнюю часть блока.Оператор if - это не блок, а функция.Таким образом, даже если код никогда не запускается в блоке, переменная все равно объявляется.

В Firefox он распознает это окно.hiya - это объявление hiya.

В IE объявление во втором скрипте перезаписывает его

Что он на самом деле делает

В firefox:

// script block 1
var hiya; // window.hiya counts as a declaration
window.hiya = "hiya"; // set

// script block 2
if (false) hiya = 1;
document.write(...)

В IE:

// script block 1
window.hiya = "hiya";

// script block 2
var hiya; // redeclared here because window.hiya "isn't" a declaration
if (false) hiya = 1; 
document.write(...)

Решение - это просто пространство имен.Вы используете одно и то же имя в двух местах и получаете к нему доступ под двумя разными именами.Либо используйте другие имена, либо используйте замыкания, чтобы задать локальную область видимости.

То, что вы столкнулись, связано с:

  1. var Быть выписом
  2. В JS нет блока
  3. Заявления выполняются до выполнения кода

Так что происходит, так это то, что JavaScript выполнит var заявление раньше, прежде чем что-либо еще, но он не оценит выражение присваивания, там hiya будет по умолчанию на значение undefined.

Как уже говорилось, т.е. исполняет какие-либо сценарии, поэтому поведение, описанное выше, приведет к hiya быть неопределенным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top