2015-03-25 15 views
14

Solo per curiosità ..Implicitamente globale "voce" variabile - differenza tra Internet Explorer e FireFox

ho questo JS Codice:

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); 

Avviso della commentato var item che lascia il ciclo con implicitamente dichiarata item variabile.

  • Se eseguo questo codice su FireFox, il risultato di allerta è: 0:a,1:b,2:c

  • Se corro lo stesso codice in Internet Explorer, il risultato è: 0:c,1:c,2:c

Ecco jsfiddle: https://jsfiddle.net/fvu9gb26/

Naturalmente, quando taccio il commento allo var item funziona allo stesso modo in ogni browser.

Qualcuno sa perché questa differenza si verifica? Grazie.

risposta

7

Fondamentalmente, questo perché l'oggetto di Internet Explorer window espone un metodo item() che lo script non può sovrascrivere.

Nella linea:

item = new Object(); 

item non è dichiarata in ambito locale, in modo che viene interpretato come una proprietà dell'oggetto globale (window.item). Su Firefox, window non espone un membro denominato item, quindi viene introdotto un nuovo membro e viene assegnato il risultato di new Object().

D'altra parte, Internet Explorer espone un metodo nativo denominato window.item(). Quel membro non è scrivibile, quindi il compito non può aver luogo - viene silenziosamente ignorato. In altre parole, item = new Object() non ha alcun effetto (beh, crea un oggetto ma non può assegnarlo in seguito).

Le assegnazioni successive a id e name terminano con la creazione di nuovi membri del metodo item(). Questi sono sempre gli stessi membri dello stesso metodo, quindi i loro valori vengono sovrascritti su ogni ciclo iterativo. Inoltre, lo stesso oggetto (il metodo item()) viene inviato all'array su ogni iterazione.

Pertanto, la matrice finisce contenente tre volte lo stesso oggetto, ei valori delle sue id e name membri sono gli ultimi valori assegnati a ciascuna (nell'ultima iterazione), rispettivamente 3 e 'c'.

+0

Grazie. Questa è stata davvero una coincidenza che ci siamo dimenticati di dichiarare 'var item' come sempre dichiariamo variabile nel nostro progetto e non fare mai affidamento su dichiarazioni implicite. E secondo, che questa variabile ha lo stesso nome di un metodo nativo su 'window object' che esiste solo in IE..wow :) –

5

Questo è difficile. Per qualche motivo oscuro, Internet Explorer ha un metodo nativo chiamato item nel contesto globale window (se qualcuno sa perché, siete invitati a condividere: non riesco a trovarlo nella documentazione). Quindi, quando si utilizza l'identificatore item senza dichiarare una variabile, fa riferimento a questo metodo.

La prima istruzione del ciclo (item = new Object();) non fa nulla perché window.item è una proprietà di sola lettura. Quindi, dopo questa istruzione, window.item è ancora la funzione nativa.

Le successive istruzioni (quelle che definisce id e name) funziona, perché mentre la proprietà window.item è di sola lettura, l'oggetto Function è indicando possono essere modificati.

Dopo i cicli, si è aggiunto lo stesso Function oggetto tre volte, e conta solo il ultima iterazione perché ignorare le proprietà id e name ogni volta.

+1

LMAO !! Mi sono imbattuto qui perché stavo usando il contesto dell'oggetto anche nel mio ciclo for. Stavo scorrendo gli articoli dal mio inventario da JSON e gli ho assegnato l'elemento variabile ... roba strana microsoft! Haha. La semplice soluzione per me era solo aggiungere var prima dell'elemento. –