2015-04-10 2 views
12

Sto avendo difficoltà a capire come questo per-ciclo termina in JavaScript:Perché "undefined" termina un ciclo in JavaScript?

var files = ["A", "B"]; 
for (var i = 0, f; f = files[i]; i++) { 
    console.log(f); 
} 

Quando viene eseguito, visualizza A e B sullo schermo, ma perché f = file [2] Fine del ciclo? Se eseguo f=files[2] nella mia console ottengo la risposta "indefinita", quindi qual è la logica alla base del fatto che questo dovrebbe terminare il ciclo?

Domanda bonus: Perché non scrivere il ciclo invece come segue?

for (var i=0; i < files.length; i++) { 
    f = files[i]; 
    console.log(f); 
} 

Questo sembra più chiara e più gestibile per me, è così c'è qualche motivo che il primo pezzo di codice sarebbe stato utilizzato nel corso del secondo?

+1

risposta bonus: perché il primo frammento di codice salva l'intera riga di codice – Igor

+10

Preferisco il secondo per consistenza in un caso in cui l'array potrebbe avere qualche valore di falsy valido come 'false',' indefinito', 'null' o' 0 '. – Prusse

+0

@I file di Igor [i] potrebbero essere facilmente inclusi nella seconda riga invece di f, quindi la riga aggiuntiva non è necessaria. questo è il modo in cui l'op lo ha scritto – rdans

risposta

22

Il ciclo termina perché undefined è un falsey value.

Il motivo per cui utilizzare uno sopra l'altro è preferenze dell'utente. Hai una preferenza mentre qualcun altro ha preferito il contrario. Qualcun altro potrebbe voler utilizzare un ciclo while. Non esiste un modo giusto.

+0

In modo errato non vuoi dire falso == indefinito? Fai ? – cafebabe1991

+1

@ cafebabe1991 'Booleano (indefinito) === falso'. La coercizione in '==' non coincide con quella, trattando 'indefinito' come solo uguale a se stesso o' null'. –

+0

Grazie per la risposta e in particolare il link ai valori di falsi. Questo ha chiarito molto e ha aiutato la mia comprensione! – Phil

2

Le matrici sono numerate a partire da zero, quindi array [] = [0,1,2]. Il codice tenta di inizializzare un valore per i file [2], che è il terzo posto nell'array, ma l'array viene definito come avente 2 spazi. Quindi, una volta che vede che ha raggiunto la fine dell'array, esce dal ciclo.

Per quanto uno dei loop sia preferito rispetto agli altri, suppongo che il secondo ciclo sarebbe migliore, perché il primo è essenzialmente quello di cercare di assegnare un valore fuori limite nell'array e, in caso contrario, di uscire. Direi che il secondo è più sicuro.

2

Si ottiene "indefinito" solo quando si esegue il codice nella console. Perché quando si esegue un codice nella console, esso restituirà "indefinito" se non restituisce alcun elemento.

1

per (ExpressionNoIn opt; Espressione opt; Espressione opt) Dichiarazione

Il primo Espressione nella dichiarazione for, se presente, viene verificata per falso-ishness per uscire dal ciclo. undefined è un falso, quindi questo termina il ciclo.

Per quanto riguarda la domanda bonus, ci sono molti modi per scrivere quel ciclo. Per me, il codice che hai proposto è più leggibile. Detto questo, è possibile utilizzare Array.forEach per iterare gli array nei browser più recenti.

1

Preferisco for (var i=0; i < files.length; i++) {}

consideri arr = [0,1,2]

for (var i = 0; i < arr.length; i++) {} sarebbe corretto ciclo su tutti gli elementi dell'array, ma non sarebbe for (var i = 0, item; item = arr[i]; i++) {} (e fallirebbe eseguire completamente).

Nota che nessuno dei due costrutti è buono per la gestione di array sparsi (ma di nuovo, dovresti probabilmente usarlo e trattarlo come un oggetto in quel punto).

Considerare l'utilizzo di Array.prototype.forEach o for(var item in arr) {} quando si tratta di array sparsi. Si noti che for(var item in arr) {} restituirà anche i valori Array.prototype e che Array.prototype.forEach è not implemented in every browser.

+0

@SalmanA Ho rimosso il mio commento. Tuttavia, uno dei modi per eseguire il looping di un array non restituisce anche 'length'? – Toothbrush

+1

@toothbrush yes, for (var item in arr) corre il rischio di iterare su variabili prototype'd. Prova 'a = [1]; a [10] = 2; Array.prototype.foo =" foo "; per (var i in a) {console.log (i)}' – 00500005

+1

@toothbrush alcuni browser lo hanno fatto e quello era sbagliato Discusso in dettaglio qui: http://stackoverflow.com/q/500504/87015 –