Jeg får denne JavaScript-feilen på konsollen min:
Uncaught SyntaxError: Uventet token ILLEGAL
Dette er koden min:
var foo = 'bar';
Det er superenkelt, som du kan se. Hvordan kan det forårsake en syntaksfeil?
Når koden analyseres av JavaScript-tolkeren, deles den opp i biter som kalles "tokens". Når et token ikke kan klassifiseres i en av de [fire grunnleggende token-typene][13], blir det merket "ILLEGAL" på de fleste implementeringer, og denne feilen blir kastet.
Den samme feilen oppstår hvis du for eksempel prøver å kjøre en js-fil med et useriøst @
tegn, en feilplassert krøllete parentes, parentes, "smarte anførselstegn", enkle anførselstegn som ikke er omsluttet riktig (f.eks. this.run('dev1)
) og så videre.
Mange forskjellige situasjoner kan forårsake denne feilen. Men hvis du ikke har noen åpenbar syntaksfeil eller ulovlig tegn, kan det være forårsaket av et usynlig ulovlig tegn. Det er det dette svaret handler om.**.
Det er et usynlig tegn i koden, rett etter semikolon. Det er tegnet [Unicode U+200B
Zero-width space][1] (også kjent som ZWSP
, HTML-entitet
). Dette tegnet er kjent for å forårsake JavaScript-syntaksfeilen Uventet token ILLEGAL
.
Jeg kan ikke si det sikkert, men jeg tipper på [jsfiddle][2]. Hvis du limer inn kode derfra, er det svært sannsynlig at den inneholder ett eller flere U+200B
-tegn. Det ser ut til at verktøyet bruker det tegnet for å kontrollere ordbryting på lange strenger.
OPPDATERING 2013-01-07 **.
Etter den siste [jsfiddle-oppdatering][jsfiddle-oppdatering], [det' s nå viser tegnet som en rød prikk][jsfiddle-demo] som codepen gjør. Tilsynelatende, det er heller ikke å sette inn
U+200B
tegn på egen hånd lenger, så dette problemet bør være mindre hyppig fra nå av. OPPDATERING 2015-03-17 Vagrant Vagrant ser ut til å noen ganger forårsake dette problemet også, på grunn av en feil i VirtualBox. Løsningen, i henhold til dette blogginnlegget er å settesendfile off;
i nginx-konfigurasjonen din, ellerEnableSendfile Off
hvis du bruker Apache. Det er også rapportert at kode limt inn fra Chrome-utviklerverktøyene kan inneholde det tegnet, men jeg klarte ikke å reprodusere det med den nåværende versjonen (22.0.1229.79 på OSX).Hvordan kan jeg oppdage det?
Tegnet er usynlig, hvordan vet vi at det er der? Du kan be redigeringsprogrammet om å vise usynlige tegn. De fleste tekstredigeringsprogrammer har denne funksjonen. Vim, for eksempel, viser dem som standard, og
ZWSP
vises som<u200b>
. Du kan også feilsøke det på nettet: jsbin viser tegnet som en rød prikk på koderutene (men ser ut til å fjerne det etter at du har lagret og lastet siden på nytt). CodePen.io viser det også som en prikk, og beholder det selv etter lagring.Relaterte problemer
Det tegnet er ikke noe dårlig, det kan faktisk være ganske nyttig. Dette eksempelet på Wikipedia viser hvordan det kan brukes til å kontrollere hvor en lang streng skal pakkes inn til neste linje. Men hvis du ikke er klar over tegnets tilstedeværelse på markeringen din, kan det bli et problem. Hvis du har det inne i en streng (f.eks.
nodeValue
i et DOM-element som ikke har noe synlig innhold), kan du forvente at en slik streng er tom, når den faktisk ikke er det (selv etter å ha bruktString.trim
).ZWSP
kan også føre til at det vises ekstra mellomrom på en HTML-side, for eksempel når den finnes mellom to<div>
-elementer (som vist på dette spørsmålet). Dette tilfellet er ikke engang reproduserbart på jsfiddle, siden tegnet ignoreres der. Et annet potensielt problem: Hvis nettsidens koding ikke gjenkjennes som UTF-8, kan det hende at tegnet faktisk vises (for eksempel somâ€'
i latin1). HvisZWSP
er til stede i CSS-koden (inline-kode eller et eksternt stilark), kan stiler heller ikke analyseres riktig, slik at noen stiler ikke blir brukt (som vist på dette spørsmålet).ECMAScript-spesifikasjonen
Jeg kunne ikke finne noen omtale av det spesifikke tegnet i ECMAScript-spesifikasjonen (versjon 3 og 5.1). Den nåværende versjonen nevner lignende tegn (
U+200C
ogU+200D
) i Section 7.1, som sier at de skal behandles somIdentifierPart
når "utenfor kommentarer, strenglitteraler og regulære uttrykk". Disse tegnene kan for eksempel være en del av et variabelnavn (ogvar x\u200c;
fungerer faktisk). Avsnitt 7.2 lister opp gyldige hvite mellomromstegn (som tabulator, mellomrom, mellomrom uten pause osv.), og nevner vagt at alle andre Unicode "mellomromseparatorer" (kategori "Zs") skal behandles som hvite mellomrom. Jeg er sannsynligvis ikke den beste personen til å diskutere spesifikasjonene i denne forbindelse, men det ser ut til atU + 200B
bør betraktes som hvitt mellomrom i henhold til det, når implementeringene (i det minste Chrome og Firefox) ser ut til å behandle dem som et uventet token (eller en del av en), noe som forårsaker syntaksfeilen.
Hvorfor leter du etter dette problemet i koden din? Selv, hvis det er kopiert inn.
Hvis du kan se, hva som skjer nøyaktig etter at du har lagret filen i synkronisert mappe - vil du se noe som *****
på slutten av filen. Det er ikke relatert til koden din i det hele tatt.
Løsning.
Hvis du bruker nginx
i vagrant-boksen - legg til i serverkonfigurasjonen:
sendfile off;
Hvis du bruker apache
i vagrant-boksen - legg til i serverkonfigurasjonen:
EnableSendfile Off;
Kilden til problemet: VirtualBox Bug
Dette kan også skje hvis du kopierer kode fra et annet dokument (som en PDF) til konsollen og prøver å kjøre det.
Jeg prøvde å kjøre litt eksempelkode fra en Javascript-bok jeg leser, og ble overrasket over at den ikke kjørte i konsollen.
Tilsynelatende introduserer kopiering fra PDF-filen noen uventede, ulovlige og usynlige tegn i koden.