2015-03-25 19 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