Неявно глобальная переменная "item" - разница между Internet Explorer и FireFox
Просто из любопытства.
У меня есть этот JS-код:
var someExternalArray = [{id: 1, name: 'a'}, {id: 2, name: 'b'}, {id: 3, name: 'c'}];
var newArray = []
//var item;
for (var i = 0; i < someExternalArray.length; i++){
item = new Object();
item.id = someExternalArray[i].id;
item.name = someExternalArray[i].name;
newArray.push(item);
}
alert('0:' + newArray[0].name + ',1:' + newArray[1].name + ',2:' + newArray[2].name);
Обратите внимание на комментарий var item
, который оставляет цикл с неявно объявленной переменной item
.
-
Если я запустил этот код в FireFox, результатом будет предупреждение: 0:a,1:b,2:c
-
Если я запустил тот же код в Internet Explorer, результатом будет:
0:c,1:c,2:c
Вот jsfiddle: https://jsfiddle.net/fvu9gb26/
Конечно, когда я раскомментирую var item
, он работает одинаково в каждом браузере.
Кто-нибудь знает, почему эта разница происходит? Спасибо.
Ответы
Ответ 1
В основном, поскольку объект Internet Explorer window
предоставляет метод item(), который ваш script не может перезаписать.
В строке:
item = new Object();
item
не объявляется в локальной области, поэтому он интерпретируется как свойство глобального объекта (window.item
). В Firefox window
не выставляет член с именем item
, поэтому вводится новый член и ему присваивается результат new Object()
.
С другой стороны, Internet Explorer предоставляет собственный метод с именем window.item()
. Этот член не может быть записан, поэтому назначение не может быть выполнено - оно игнорируется. Другими словами, item = new Object()
не имеет никакого эффекта (ну, он создает объект, но не может назначить его впоследствии).
Последующие назначения id
и name
завершают создание новых членов метода item()
. Это всегда одни и те же члены одного и того же метода, поэтому их значения перезаписываются на каждой итерации цикла. Кроме того, тот же объект (метод item()
) помещается в массив на каждой итерации.
Следовательно, массив заканчивается, содержащий три раза один и тот же объект, а значения его членов id
и name
являются последними присвоенными им значениями (в последней итерации) соответственно 3
и 'c'
.
Ответ 2
Это сложно. По какой-то непонятной причине Internet Explorer имеет собственный метод item
в глобальном контексте window
(если кто-то знает, почему вы можете делиться: я не могу найти его в документации). Итак, когда вы используете идентификатор item
без объявления переменной, он ссылается на этот метод.
Первая инструкция в цикле (item = new Object();
) ничего не делает, потому что window.item
является свойством readonly. Итак, после этой инструкции window.item
по-прежнему является нативной функцией.
Следующие команды (те, которые устанавливают id
и name
) работают, потому что, пока свойство window.item
доступно только для чтения, объект Function
, на который он указывает, может быть изменен.
После циклов вы добавили один и тот же объект Function
три раза, и только последняя итерация подсчитывается, потому что вы каждый раз переопределяете свойства id
и name
.