隐式全局 "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 变量。

这是 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() 根本没有效果(好吧,它确实创建了一个对象,但之后不能分配它)。

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

因此,数组最终包含了相同对象的三倍,其 idname 成员的值分别是分配给它们的最后值(在最后一次迭代中) 3'c'.

这很棘手。由于一些不明原因,Internet Explorer 在全局上下文 window 中有一个名为 item 的本机方法(如果有人知道为什么,欢迎分享:我在文档中找不到它)。所以,当你在没有声明变量的情况下使用标识符item时,它指的是这个方法。

循环中的第一条指令 (item = new Object();) 什么都不做,因为 window.item 是只读的 属性。所以,在这条指令之后,window.item 仍然是原生函数。

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

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