2015-03-25 20 views
14

只是出于好奇之差..隐含全球“项”变量 - 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变量。

  • 如果我运行火狐这段代码,警报的结果是:0:a,1:b,2:c

  • 如果我在Internet Explorer中运行相同的代码,结果是: 0:c,1:c,2:c

这里是jsfiddle:https://jsfiddle.net/fvu9gb26/

当然,当我取消注释它在每个浏览器中都以相同的方式工作。

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

回答

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成员的值是分配给它们(在最后迭代)的最后值,3'c'

+0

谢谢。这真的是一个巧合,我们忘记声明'var item',因为我们总是在我们的项目中声明变量,并且决不依赖隐式声明。第二,这个变量与'window object'上的一些本地方法具有相同的名称,它只存在于IE中.wow :) – 2015-03-26 06:02:55

5

这很棘手。出于某种不明原因,Internet Explorer在全球范围内有一个名为item的本地方法window(如果有人知道为什么,欢迎分享:我无法在文档中找到它)。因此,当您使用标识符item而未声明变量时,它指的是此方法。

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

下一个指令(在其设置idname)的作品,因为在财产window.item是只读的,在Function对象它所指向可以修改。

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

+1

LMAO !!我偶然发现了这里,因为我在for循环中也使用了项目上下文。我正在从JSON的库存中循环项目,并将变量项目分配给它......奇怪的东西微软!哈哈。对我来说简单的修复就是在item之前添加var。 – 2015-05-25 06:09:57