隐含全球性的"项目"变量 - Internet Explorer和FireFox之间的差异

时间:2015-03-25 10:48:47

标签: javascript internet-explorer scope global-variables

出于好奇......

我有这个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时,它在每个浏览器中的工作方式都相同。

有谁知道为什么会出现这种差异?谢谢。

2 个答案:

答案 0 :(得分:7)

基本上,这是因为Internet Explorer的window对象公开了一个脚本无法覆盖的item()方法。

在行中:

item = new Object();

item未在本地范围内声明,因此它被解释为全局对象(window.item)的属性。在Firefox上,window不会公开名为item的成员,因此会引入新成员并为其分配new Object()的结果。

另一方面,Internet Explorer公开名为window.item()的本机方法。该成员不可写,因此无法进行任务 - 它会被默默地忽略。换句话说,item = new Object()根本没有效果(好吧,它确实创建了一个对象,但之后无法分配它)。

idname的后续分配最终会创建item()方法的新成员。它们始终是同一方法的相同成员,因此在每次循环迭代时都会覆盖它们的值。此外,每次迭代都会将相同的对象(item()方法)推送到数组中。

因此,数组最终包含相同对象的三倍,其idname成员的值分别是分配给它们的最后一个值(在上一次迭代中){{ 1}}和3

答案 1 :(得分:5)

这很棘手。出于某些不明原因,Internet Explorer在全局上下文item中有一个名为window的本机方法(如果有人知道原因,欢迎您分享:我无法在其中找到它文件)。因此,当您使用标识符item而不声明变量时,它会引用此方法。

循环中的第一条指令(item = new Object();)不执行任何操作,因为window.item是一个只读属性。因此,在此指令之后,window.item仍然是本机函数。

下一条说明(设置idname的说明)有效,因为虽然属性window.item是只读的,但它指向的Function对象可以修改。

在循环之后,您添加了相同的Function对象三次,并且只有最后一次迭代计数,因为您每次都会覆盖idname属性。