Почему IE запускает nuke window.Переменные ABC?
-
25-09-2019 - |
Вопрос
При запуске следующего блока кода 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(...)
Решение - это просто пространство имен.Вы используете одно и то же имя в двух местах и получаете к нему доступ под двумя разными именами.Либо используйте другие имена, либо используйте замыкания, чтобы задать локальную область видимости.
То, что вы столкнулись, связано с:
var
Быть выписом- В JS нет блока
- Заявления выполняются до выполнения кода
Так что происходит, так это то, что JavaScript выполнит var
заявление раньше, прежде чем что-либо еще, но он не оценит выражение присваивания, там hiya
будет по умолчанию на значение undefined
.
Как уже говорилось, т.е. исполняет какие-либо сценарии, поэтому поведение, описанное выше, приведет к hiya
быть неопределенным.