lascia parola chiave nel ciclo for

let ECMAScript 6 dovrebbe fornire scope di blocco senza problemi di sollevamento. Qualcuno può spiegare perché nel codice sotto i nella funzione si risolva l’ultimo valore dal ciclo (proprio come con var ) invece del valore dall’iterazione corrente?

 "use strict"; var things = {}; for (let i = 0; i < 3; i++) { things["fun" + i] = function() { console.log(i); }; } things["fun0"](); // prints 3 things["fun1"](); // prints 3 things["fun2"](); // prints 3 

Secondo MDN, l’ uso di let nel ciclo for dovrebbe bind la variabile nell’ambito del corpo del ciclo. Le cose funzionano come mi aspetterei da loro quando uso una variabile temporanea all’interno del blocco. Perché è necessario?

 "use strict"; var things = {}; for (let i = 0; i < 3; i++) { let index = i; things["fun" + i] = function() { console.log(index); }; } things["fun0"](); // prints 0 things["fun1"](); // prints 1 things["fun2"](); // prints 2 

Ho testato la sceneggiatura con Traceur e il node --harmony .

La risposta di Squint non è più aggiornata. Nella specifica ECMA 6 , il comportamento specificato è quello in

 for(let i;;){} 

i una nuova associazione per ogni iterazione del ciclo.

Ciò significa che ogni chiusura acquisisce una diversa istanza. Quindi il risultato di 012 è il risultato corretto al momento. Quando esegui questo in Chrome v47 +, ottieni il risultato corretto. Quando lo esegui in IE11 e Edge, attualmente il risultato errato ( 333 ) sembra essere prodotto.

Ulteriori informazioni su questo bug / funzionalità sono disponibili nei link in questa pagina ;

Da quando viene utilizzata l’espressione let , ogni iterazione crea un nuovo ambito lessicale incatenato allo scope precedente. Ciò ha implicazioni sulle prestazioni per l’utilizzo dell’espressione let , che viene riportata qui .

Ho passato questo codice attraverso Babel in modo che possiamo capire il comportamento in termini di ES5 familiare:

 for (let i = 0; i < 3; i++) { i++; things["fun" + i] = function() { console.log(i); }; i--; } 

Ecco il codice transpiled per ES5:

 var _loop = function _loop(_i) { _i++; things["fun" + _i] = function () { console.log(_i); }; _i--; i = _i; }; for (var i = 0; i < 3; i++) { _loop(i); } 

Possiamo vedere che vengono utilizzate due variabili.

  • Nell'ambito esterno i è la variabile che cambia man mano che iteriamo.

  • Nell'ambito interno _i è una variabile univoca per ogni iterazione. Alla fine ci saranno tre istanze separate di _i .

    Ogni funzione di callback può vedere il suo corrispondente _i , e potrebbe persino manipolarlo se lo desidera, indipendentemente dal _i s in altri ambiti.

    (Puoi confermare che ci sono tre diversi _i facendo console.log(i++) all'interno del callback. Cambiare _i in una callback precedente non influisce sull'output da callback successivi.)

Alla fine di ogni iterazione, il valore di _i viene copiato in i . Pertanto, la modifica della variabile interna unica durante l'iterazione influisce sulla variabile iterata esterna.

È bello vedere che ES6 ha continuato la tradizione di lunga data di WTFJS.

IMHO: i programmatori che per primi hanno implementato questo LET (producendo i risultati della tua versione iniziale) lo hanno fatto correttamente rispetto alla sanità mentale; potrebbero non aver dato un’occhiata alle specifiche durante l’implementazione.

Ha più senso che venga utilizzata una singola variabile, ma portata al ciclo for. Soprattutto perché uno dovrebbe sentirsi libero di cambiare quella variabile a seconda delle condizioni all’interno del ciclo.

Ma aspetta: puoi cambiare la variabile del ciclo. WTFJS !! Tuttavia, se si tenta di modificarlo nel tuo ambito interno, non funzionerà ora perché è una nuova variabile.

Non mi piace quello che devo fare Per ottenere quello che voglio (una singola variabile che è locale per il):

 { let x = 0; for (; x < length; x++) { things["fun" + x] = function() { console.log(x); }; } } 

Dove modificare la versione più intuitiva (se immaginaria) per gestire una nuova variabile per iterazione:

 for (let x = 0; x < length; x++) { let y = x; things["fun" + y] = function() { console.log(y); }; } 

È chiaro cosa intendi con la variabile y. O lo sarebbe stato se SANITY avesse governato l'universo.

Quindi il tuo primo esempio ora funziona in FF; produce lo 0, 1, 2. Si arriva a chiamare il problema risolto. Chiamo il problema WTFJS.

ps. Il mio riferimento a WTFJS è da JoeyTwiddle sopra; Sembra un meme che avrei dovuto conoscere prima di oggi, ma oggi è stato un grande momento per impararlo.