Javascript redeclared global variable переопределяет старое значение

На днях я столкнулся с интересной проблемой и задавался вопросом, может ли кто-нибудь пролить свет на то, почему это происходит. Вот что я делаю (для целей этого примера я немного пошатнул пример):

  • Я создаю глобальную область с переменной квадратной скобкой и присваиваю ей значение.
  • Позже я объявляю var с тем же именем, что и тот, который я только что создал. Примечание. Я не назначаю значение. Поскольку это переопределение одной и той же переменной, старое значение не должно переоцениваться, как описано здесь: http://www.w3schools.com/js/js_variables.asp

    //create global variable with square bracket notation
    window['y'] = 'old';
    
    //redeclaration of the same variable
    var y;
    
    if (!y) y = 'new';
    
    alert(y); //shows New instead of Old
    
  • Проблема состоит в том, что старое значение действительно перегружается и в приведенном выше примере. предупреждение показывает "новое" вместо "старого". Почему?

Я предполагаю, что другой способ сформулировать мой вопрос заключается в том, как приведенный выше код отличается семантикой из приведенного ниже кода:

//create global variable 
var y = 'old';

//redeclaration of the same variable
var y;

if (!y) y = 'new';

alert(y); //shows Old

Обновление 1. Основываясь на некоторых комментариях и ответах, я перефразирую этот пример, чтобы лучше отразить мою оригинальную проблему.

Создайте 2 файла javascript со следующим содержимым: Script1

//create global variable with square bracket notation
window['y'] = 'old';

Скрипт2

//redeclaration of the same variable
var y;

if (!y) y = 'new';

alert(y); //shows New instead of Old in IE

Включите эти 2 файла в свой html файл

<html>
 <head></head>
 <body>

  <script type="text/javascript" src="my.js"></script>
  <script type="text/javascript" src="my2.js"></script>

 </body>
</html>

Открытие этой страницы в Firefox и Chrome предупреждает "старый", что является ожидаемым поведением. Однако в IE 8 страница будет на самом деле предупреждать "новый"

Обновить 2 вопрос: Измененная глобальная переменная javascript переопределяет старое значение в IE

Ответ 1

Операция var подвержена подъему, это означает, что когда код входит в контекст выполнения (непосредственно перед фактической средой выполнения), операторы var и function становятся доступными для своей охватывающей области.

В действительности ваш код оценивается следующим образом:

Первый пример:

var y;
window['y'] = 'old';

if (!y) y = 'new';

alert(y);

Второй пример:

var y;
y = 'old';

if (!y) y = 'new';

alert(y);

Когда оператор var поднят, вы увидите фактическое поведение, которое имеет код.

См. также:

Ответ 2

? Я просто проверил ваш код, и он показывает "старый", и я тестировал FF, Chrome, Safari (ПК) и IE8.

Посмотрите здесь: http://jsbin.com/ifare/edit

Ответ 3

Когда вы обновили y с помощью var y;, теперь он undefined, поэтому if(!undefined) получает значение true.

Добавьте еще одно предупреждение в свой пример, чтобы увидеть это:

//create global variable with square bracket notation
window['y'] = 'old';

//redeclaration of the same variable
var y;
alert(y); //undefined

if (!y) y = 'new';

alert(y); // new

var не будет инициализировать переменную дважды, но она перезапишет одну, не инициализированную в первый раз (потому что это новая, более локальная переменная), которую делает стиль window['y'], добавляя его к объекту окна. Возьмите это, например:

//create global variable with square bracket notation
window['y'] = 'old';

//redeclaration of the same variable
var y;
alert(y); //undefined

alert(window.y); //old

if (!y) y = 'new';

alert(y); //shows New instead of Old
alert(window.y);​ //still old

Ответ 4

Вы не можете "переопределять" переменные как таковые в пределах той же области действия в JS.

var x = "foo"
function a()
{
  alert(x); // undefined
  var x;
}

В функции a переменная x является локальной, поскольку она имеет var x. Не имеет значения, идет ли оно до или после использования.

Аналогично:

function b()
{
  var z = 1;
  if (true)
  {
    var z = 2;
  }
  alert(z); // 2
}

потому что не существует такой области, как область "block".