Perché JavaScript è Per … In loop non raccomandato per gli arrays?

Ho letto da qualche parte (mi dispiace, non riesco a trovare il collegamento) che il For … In loop non è raccomandato per gli arrays. Si dice qui: http://www.openjs.com/articles/for_loop.php che si intende per arrays associativi, e in http://www.w3schools.com/js/js_loop_for_in.asp che è per iterare attraverso tutte le properties; di un object (non dice che può essere utilizzato su arrays). Non so chi credere. Non voglio che questa domanda diventi un dibattito. Voglio solo sapere se posso utilizzare questo codice nel mio codice senza effetti collaterali imprevisti. Grazie!

Un arrays è un object e gli elementi di matrix sono semplicemente properties; con l'indice numbersco convertito in string. Ad esempio, arr [123] si riferisce ad una properties; "123" nell'object arrays arrays arr.

Il for ... in build opere su tutti gli oggetti , non solo arrays, e che è causa di confusione.

Quando qualcuno for ... in un arrays, più spesso il programmatore intende itare solo tutti gli elementi , anche molto probabilmente in ordine . Ad esempio, se l'arrays contiene un gruppo di numbers, il programmatore ha probabilmente l'intento di iterare un stream di numbers. La semantica è così simile alla iterazione di matrix in altri linguaggi di programmazione che è molto facile confondere.

In JavaScript, questo costrutto non esegue l'iterazione degli elementi di matrix in ordine. Esegue tutti i nomi delle properties; dell'arrays (inclusi i nomi delle funzioni prototipate ereditate, tutte le properties; aggiunte, altre properties; non elementari aggiunte ad esso ecc.) E non in ordine . Nei browser precedenti, troverà anche la length della properties;, anche se in browser recenti queste properties; sono ora definite per essere nascoste per questa ragione esatta – le persone continuano ad avventurarsi!

Con l'arrays di interi sopra, non si ottiene un stream di numbers, ma un stream di stringhe di text. E non i valori dell'elemento, ma i nomi delle properties; (che sono solo gli indici numbersci in nessun ordine). Questo non è probabilmente quello che significa il programmatore, se viene da un altro linguaggio di programmazione. Se gli elementi memorizzati nell'arrays si verificano come valori numbersci simili, confonde l'inferno da tutti.

Ecco perché non dovresti farlo. Non dovresti usare un costrutto di lingua che sembra che fa cose ovvie, ma in realtà fa cose completamente diverse. Crea bug che sono molto oscuri e molto difficili da trovare.

Ho testato l'iterazione di matrix in diversi browser (FireFox 3, Opera 9, IE6, IE9 beta, Chrome) e funziona bene; Mi sembra di ricordare alcune incompatibilità tra browser, ma devo essere sbagliato.

C'è ancora un caveat però:

Come hai già detto, il for ... in syntax viene utilizzato per iterare sulle properties; di un object; così, con un arrays, tutte le properties; di quel object arrays verranno anche ripetute insieme agli elementi. Normalmente, l'object arrays presenta solo properties; corrispondenti alle chiavi in ​​esso, ma se un altro script modifica Array.prototype (ad esempio un framework), i methods / attributi aggiunti verrebbero inaspettatamente visualizzati anche Array.prototype .

Un paio di buone ragioni sono riportte nella documentazione Prototype.js: http://www.prototypejs.org/api/arrays

Fondamentalmente, l'utilizzo di … per l'iterazione di un arrays è fragile poiché qualsiasi altro codice può aggiungere properties; al prototipo Array, che diventerà quindi properties; enumerabili in each object di arrays.

Iterazione su un arrays che utilizza for(... in ...) non otterrà tasti numbersci, ottiene i valori di string.

Sarà properties; properties; definite nel prototipo, quindi se qualsiasi codice estende Array , ad esempio:

 Array.prototype.each = ...; 

allora vednetworking la properties; each .

Non vi è alcuna garanzia che otterrai le properties; nell'ordine di indice di matrix. Ad esempio, provare a ripetere l'iterazione

 var arr = [] arr[1] = 1; arr[0] = 0; 

Su molti browser avrai 1 prima di 0 .

E non sei garantito per get tutti gli indici. Prova a ripetere l'iterazione

 [0,,,3] 

non otterrai l'indice 1 o 2 .