隐式全局 "item" 变量 - Internet Explorer 和 FireFox 之间的区别
Implicitly global "item" variable - difference between Internet Explorer and 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
时,它在每个浏览器中的工作方式都相同。
有谁知道为什么会出现这种差异?谢谢。
基本上,这是因为 Internet Explorer 的 window
对象公开了您的脚本无法覆盖的 item() 方法。
行中:
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'
.
这很棘手。由于一些不明原因,Internet Explorer 在全局上下文 window
中有一个名为 item
的本机方法(如果有人知道为什么,欢迎分享:我在文档中找不到它)。所以,当你在没有声明变量的情况下使用标识符item
时,它指的是这个方法。
循环中的第一条指令 (item = new Object();
) 什么都不做,因为 window.item
是只读的 属性。所以,在这条指令之后,window.item
仍然是原生函数。
接下来的指令(设置 id
和 name
的指令)有效,因为虽然 属性 window.item
是只读的,但 Function
对象是指向可以修改。
循环后,您添加了相同的 Function
对象三次,只有最后一次迭代才算数,因为您每次都覆盖了 id
和 name
属性。
出于好奇..
我有这个 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
时,它在每个浏览器中的工作方式都相同。
有谁知道为什么会出现这种差异?谢谢。
基本上,这是因为 Internet Explorer 的 window
对象公开了您的脚本无法覆盖的 item() 方法。
行中:
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'
.
这很棘手。由于一些不明原因,Internet Explorer 在全局上下文 window
中有一个名为 item
的本机方法(如果有人知道为什么,欢迎分享:我在文档中找不到它)。所以,当你在没有声明变量的情况下使用标识符item
时,它指的是这个方法。
循环中的第一条指令 (item = new Object();
) 什么都不做,因为 window.item
是只读的 属性。所以,在这条指令之后,window.item
仍然是原生函数。
接下来的指令(设置 id
和 name
的指令)有效,因为虽然 属性 window.item
是只读的,但 Function
对象是指向可以修改。
循环后,您添加了相同的 Function
对象三次,只有最后一次迭代才算数,因为您每次都覆盖了 id
和 name
属性。