Nessun punto e virgola prima che stia causando un errore in Javascript?

var a = [1,2,3,4]; var b = [10,20,30,40]; console.log([a,b].length) [a,b].some(function(x){ x.push(x.shift()) }); 

Sono rimasto estremamente sorpreso oggi quando questo codice ha causato

 [a,b].some(function(x){ x.push(x.shift()) }); ^ TypeError: Cannot call method 'some' of undefined 

Ovviamente l’inserimento automatico del punto e virgola di JavaScript non funziona come previsto qui. Ma perché?

So che potresti raccomandare di usare ; ovunque per evitare qualcosa del genere, ma la domanda non riguarda se è meglio usarla ; o no. Mi piacerebbe sapere cosa succede esattamente qui?

Quando sono preoccupato per l’inserimento del punto e virgola, penso a come sarebbero le linee in questione senza spazi bianchi tra loro. Nel tuo caso, sarebbe:

 console.log([a,b].length)[a,b].some(function(x){ etc }); 

Qui stai dicendo al motore Javascript di chiamare console.log con la lunghezza di [a,b] , quindi di guardare l’indice [a,b] del risultato di quella chiamata.

console.log restituisce una stringa, quindi il codice tenterà di trovare la proprietà b di quella stringa, che non è definita, e la chiamata a undefined.some() esito negativo.

È interessante notare che str[a,b] si risolverà in str[b] assumendo che str sia una stringa. Come sottolinea Kamil, a,b è un’espressione Javascript valida, e il risultato di tale espressione è semplicemente b .

In generale, si potrebbe dire che i semi-punti impliciti possono facilmente fallire quando si definisce un array su una nuova riga, poiché un array definito su una nuova riga viene interpretato come un accesso di proprietà del valore dell’espressione sulla riga precedente.

Javascript considera solo le nuove righe per contrassegnare la fine di un’istruzione se non termina l’istruzione dopo che questa nuova riga causerebbe un errore di analisi. Vedi Quali sono le regole per l’inserimento automatico del punto e virgola di JavaScript (ASI)? ed EcmaScript 5 specifiche per le regole esatte. (Grazie a Rob W e alle luci delle stelle)

Quello che succede è il seguente:

Il codice viene interpretato come

 console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) }); 

vale a dire tutto come una dichiarazione.

Ora analizza la dichiarazione:

some sono chiamati sul valore di console.log([a,b].length)[a,b]

il valore di console.log([a,b].length)[a,b] viene calcolato prendendo il valore restituito di console.log([a,b].length) ( undefined ) e quindi cercando di accedere alla proprietà con il nome del valore di a,b . a,b valuta il valore di b (provalo nella tua console). Non esiste una proprietà con il valore di b undefined , quindi anche il valore risultante sarà undefined .

Non c’è alcun metodo su undefined , quindi l’errore.

JavaScript non considera ogni interruzione di riga come un punto e virgola. Solitamente tratta le interruzioni di riga come punti e virgola solo se non è in grado di analizzare il codice senza il punto e virgola. Fondamentalmente, JavaScript considera un’interruzione di riga come un punto e virgola se il successivo carattere non spaziale non può essere interpretato come una continuazione dell’istruzione corrente. JavaScript – The Definitive Guide: 6a Ed. sezione 2.4

Quindi, nel tuo caso, sta interpretando la linea come qualcosa di simile

 console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) }); 

E questo è il motivo dell’errore. JavaScript sta tentando di eseguire l’accesso all’array sui risultati di console.log([a,b].length) . A seconda del motore JavaScript e del valore di ritorno di console.log , potresti ricevere diversi errori.

Se è l’ultima istruzione della funzione o del stream, puoi evitare ';' ma si consiglia di mettere ';' alla fine di ogni affermazione per evitare tale errore.