Brak widocznej przyczyny „Nieoczekiwany token NIELEGALNY”

270

Na mojej konsoli pojawia się błąd JavaScript:

Uncaught SyntaxError: Nieoczekiwany token NIELEGALNY

To jest mój kod:

var foo = 'bar';​

To bardzo proste, jak widać. Jak może to powodować błąd składniowy?

bfavaretto
źródło
9
Dla przyszłych czytelników: jeśli napotkasz ten błąd podczas korzystania z Vagrant - ta odpowiedź może być również pomocna: stackoverflow.com/questions/9479117/…
OZ_
W przypadku, gdy występuje to w WordPress, kolejkuj skrypty z functions.php. Miałem określony szablon, w którym dzwoniłem do JS bezpośrednio z szablonu. Przejście do kolejki warunkowej w wp_head lub wp_footer rozwiązało ten problem.
Alpesh Shah
7
Uwaga moderatora: Usunąłem tutaj kilka odpowiedzi, które tak naprawdę nie odpowiadają na pytanie. To nie jest, powtarzam, nie miejsce, w którym można wypisać wszystkie możliwe rzeczy, które możesz zrobić w JavaScript, które spowodują ten błąd. Pytanie ma bardzo specyficzną okoliczność, która nie obejmuje żadnego z tych scenariuszy, a wszystkie te przykłady po prostu nie odpowiadają na pytanie.
animuson
3
Wow, policja SO miała dzień polowy z tym pytaniem. Na szczęście niektóre istotne informacje są nadal widoczne w usuniętych odpowiedziach.
cdonner,

Odpowiedzi:

493

Błąd

Kiedy kod jest analizowany przez interpreter JavaScript, zostaje podzielony na części zwane „tokenami”. Gdy tokena nie można zaklasyfikować do jednego z czterech podstawowych typów tokena , w większości implementacji zostaje on oznaczony jako „NIELEGALNY”, a błąd zostaje zgłoszony.

Ten sam błąd pojawia się, gdy na przykład próbujesz uruchomić plik js z nieuczciwym @znakiem, źle umieszczony nawias klamrowy, nawias kwadratowy, „inteligentne cytaty”, pojedyncze cudzysłowy niepoprawnie ujęte (np. this.run('dev1)) I tak dalej.

Ten błąd może powodować wiele różnych sytuacji. Ale jeśli nie masz oczywistego błędu składniowego lub niedozwolonego znaku, może to być spowodowane niewidocznym niedozwolonym znakiem. O to właśnie chodzi w tej odpowiedzi.

Ale nie widzę nic nielegalnego!

W kodzie znajduje się niewidoczny znak, tuż po średniku. Jest to znak U+200Bspacji o zerowej szerokości Unicode (inaczej ZWSPencja HTML ​). Znany jest ten znak, który powoduje Unexpected token ILLEGALbłąd składniowy JavaScript.

A skąd to się wzięło?

Nie wiem na pewno, ale mój zakład dotyczy jsfiddle . Jeśli stamtąd wkleisz kod, najprawdopodobniej będzie zawierać jeden lub więcej U+200Bznaków. Wygląda na to, że narzędzie używa tego znaku do kontrolowania zawijania słów na długich ciągach.

AKTUALIZACJA 2013-01-07

Po ostatniej jsfiddle aktualizacji , to teraz przedstawiający postać jako czerwona kropka jak codepen robi. Najwyraźniej nie jest U+200Bjuż samodzielnym wstawianiem postaci, więc ten problem powinien być teraz mniej częsty.

AKTUALIZACJA 17.03.2015

Vagrant wydaje się czasami powodować ten problem, z powodu błędu w VirtualBox . Rozwiązaniem, zgodnie z tym postem na blogu, jest ustawienie sendfile off;w konfiguracji nginx lub EnableSendfile Offjeśli używasz Apache.

Doniesiono również, że kod wklejony z narzędzi programistycznych Chrome może zawierać ten znak, ale nie byłem w stanie go odtworzyć w bieżącej wersji (22.0.1229.79 na OSX).

Jak mogę to zauważyć?

Postać jest niewidoczna. Skąd wiemy, że tam jest? Możesz poprosić swojego redaktora o wyświetlanie niewidzialnych znaków. Większość edytorów tekstu ma tę funkcję. Na przykład Vim wyświetla je domyślnie, a ZWSPpokazuje jako <u200b>. Możesz także debugować go w trybie online: jsbin wyświetla znak jako czerwoną kropkę na panelach kodu (ale wydaje się, że usuwa go po zapisaniu i ponownym załadowaniu strony). CodePen.io wyświetla go również jako kropkę i zachowuje go nawet po zapisaniu.

Powiązane problemy

Ta postać nie jest czymś złym, może być naprawdę przydatna. Ten przykład na Wikipedii pokazuje, jak można go użyć do kontrolowania, gdzie długi łańcuch powinien być zawinięty do następnego wiersza. Jeśli jednak nie jesteś świadomy obecności postaci na znacznikach, może to stanowić problem. Jeśli masz go wewnątrz ciągu znaków (np. nodeValueElementu DOM, który nie ma widocznej zawartości), możesz oczekiwać, że taki ciąg znaków będzie pusty, podczas gdy w rzeczywistości tak nie jest (nawet po zastosowaniu String.trim).

ZWSPmoże również powodować wyświetlanie dodatkowych spacji na stronie HTML, na przykład gdy znajdzie się między dwoma <div>elementami (jak widać na tym pytaniu ). Ten przypadek nie jest nawet odtwarzalny w jsfiddle, ponieważ znak jest tam ignorowany.

Kolejny potencjalny problem: jeśli kodowanie strony internetowej nie zostanie rozpoznane jako UTF-8, znak może faktycznie zostać wyświetlony ( ​na przykład w Latin1).

Jeśli ZWSPjest obecny w kodzie CSS (kod wbudowany lub zewnętrzny arkusz stylów), style również nie mogą zostać poprawnie przeanalizowane, więc niektóre style nie zostaną zastosowane (jak widać na tym pytaniu ).

Specyfikacja ECMAScript

Nie mogłem znaleźć żadnej wzmianki o tym konkretnym znaku w specyfikacji ECMAScript (wersje 3 i 5.1 ). Obecna wersja wymienia podobne znaki ( U+200Ci U+200D) w sekcji 7.1 , która mówi, że powinny być traktowane jako IdentifierParts, gdy „poza komentarzami, literałami ciągów i literałami wyrażeń regularnych”. Znaki te mogą na przykład być częścią nazwy zmiennej (i var x\u200c;faktycznie działają).

W sekcji 7.2 wymieniono prawidłowe znaki spacji (takie jak tabulator, spacja, spacja bez przerw itp.) I niejasno wspomina, że ​​każdy inny „separator spacji” Unicode (kategoria „Z”) powinien być traktowany jako spacja. Prawdopodobnie nie jestem najlepszą osobą do omawiania specyfikacji w tym zakresie, ale wydaje mi się, że U+200Bnależy to uznać za białą przestrzeń zgodnie z tym, kiedy w rzeczywistości implementacje (przynajmniej Chrome i Firefox) wydają się traktować je jako nieoczekiwane token (lub część jednego), powodujący błąd składniowy.

bfavaretto
źródło
codepen.io wydaje się również wyświetlać ten znak. VIM i VI, również notatnik ++ wyświetla go.
rlemon
Dzięki @rlemon, dodałem przykład CodePen do odpowiedzi. Ładna strona, nie wiedziałam o tym.
bfavaretto
Natknąłem się na ten problem podczas kopiowania / wklejania kodu dla klasy testTwo z tego pytania SO przy użyciu Chromium. Najwyraźniej parser zadławił się podświetleniem składni functionsłowa kluczowego, które było niewidoczne w Vimie, dopóki go nie zaznaczyłem za pomocą metody FAQ „Podświetl wszystkie znaki niedrukowalne”. Ahh, byłoby miło, gdyby istniał sposób na kopiowanie tylko znaków w zakresie 32..127 (ale prawdopodobnie jest na to aplikacja :))
ack
1
@bfavaretto, tylko we fragmencie kodu w trybie edycji. Nie w treści pytania powinienem o tym wspomnieć. (Testowany na Chrome 43.0.2357.124 m)
Fernando Leal
1
Wiele edytorów tekstu pozwala na zmianę kodowania znaków w pliku. Jest to niezwykle przydatne, aby znaleźć takie obrażające postacie. Moim rozwiązaniem było tymczasowe przełączenie z kodowania UTF-8 na kodowanie ANSI, usunięcie nieprawidłowych znaków, a następnie przełączenie z powrotem. Użyłem darmowego Notepad ++ w systemie Windows. EDYCJA: Okazuje się, że przegapiłem opcję Notepad ++ dla „Wyświetlanie wszystkich znaków”. Ten sam wynik, mniej kłopotów: D
mbargiel
64

dlaczego szukasz tego problemu w swoim kodzie? Nawet jeśli jest skopiowany.

Jeśli widzisz, co dokładnie dzieje się po zapisaniu pliku w zsynchronizowanym folderze - zobaczysz coś *****na końcu pliku. To wcale nie jest związane z twoim kodem.

Rozwiązanie.

Jeśli używasz nginxw błędnym polu - dodaj do konfiguracji serwera:

sendfile off;

Jeśli używasz apachew błędnym polu - dodaj do konfiguracji serwera:

EnableSendfile Off;

Źródło problemu: Błąd VirtualBox

Nikolay Fominyh
źródło
6
Dosłownie uratowałeś mi dzień. Walczyłem z Nginx + Vagrant przez cały wieczór i to rozwiązało.
fradeve
2
Czy nie oczekiwać, że jest to prawidłowa odpowiedź (dla mnie), ale to było, dzięki tak dużo.
Charlotte,
2
Właściwie to przestało działać. Z drugiej strony jest tu wiele warstw symlinkowania, więc po prostu nie udało mi się.
Charlotte
Dzięki - byłem w włóczęgi z nginx. Widziałem także ten problem w podobnych konfiguracjach Apache.
Cameron
dla apache: EnableSendfile Off
jamlee
7

Może się tak również zdarzyć, jeśli kopiujesz kod z innego dokumentu (np. PDF) na konsolę i próbujesz go uruchomić.

Próbowałem uruchomić przykładowy kod z książki JavaScript, którą czytam, i byłem zaskoczony, że nie uruchomił się w konsoli.

Najwyraźniej kopiowanie z pliku PDF wprowadza do kodu pewne nieoczekiwane, nielegalne i niewidoczne znaki.

Kyle Pennell
źródło
5

Miałem ten sam problem na moim komputerze Mac i stwierdziłem, że było tak, ponieważ Mac zastępował standardowe cytaty kręconymi cytatami, które są niedozwolonymi znakami javascript.

Aby to naprawić, musiałem zmienić ustawienia na moim komputerze Mac Preferencje systemowe => Klawiatura => Tekst (karta) odznacz Użyj inteligentnych cytatów i myślników (domyślnie zaznaczono).

użytkownik3360944
źródło
5

Wystąpił ten błąd w chrome, gdy po wierszu wskazanym przez błąd miałem nieskończony ciąg znaków. Po zamknięciu ciągu błąd zniknął.

Przykład z błędem:

var file = files[i]; // SyntaxError: Unexpected token ILLEGAL

jQuery('#someDiv').innerHTML = file.name + " (" + formatSize(file.size) + ") "
    + "<a href=\"javascript: something('"+file.id+');\">Error is here</a>";

Przykład bez błędu:

var file = files[i]; // No error

jQuery('#someDiv').innerHTML = file.name + " (" + formatSize(file.size) + ") "
    + "<a href=\"javascript: something('"+file.id+"');\">Error was here</a>";
Ozzy
źródło
2
Musiałem przeanalizować twoje dwa przykłady, aby zrozumieć różnicę, a kiedy to zrobiłem, natychmiast odkryłem swój własny problem.
Ben Harold
3

Jeśli używasz włóczęgi instalacyjnej nginx + uwsgi, głównym problemem jest błąd wirtualnego pudełka z plikiem wysyłania, jak wspomniano w niektórych odpowiedziach. Jednak aby to rozwiązać, musisz wyłączyć sendfile zarówno w nginx, jak i uwsgi.

  1. W nginx.conf wyślij plik

  2. uwsgi application / config --disable-sendfile

msrivas
źródło
2

Podczas uruchamiania systemu OS X system plików tworzy ukryte widelce w zasadzie wszystkich twoich plików, jeśli znajdują się one na dysku twardym, który nie obsługuje HFS +. Może to czasem (tak mi się teraz zdarzyło) doprowadzić do tego, że silnik JavaScript próbuje uruchomić widelec danych zamiast kodu, który zamierzasz uruchomić. Kiedy tak się stanie, otrzymasz również

SyntaxError: Unexpected token ILLEGAL

ponieważ widelec danych twojego pliku będzie zawierał znak Unicode U + 200B. Usunięcie pliku rozwidlenia danych spowoduje, że skrypt uruchomi rzeczywisty, zamierzony kod, zamiast rozwidlenia danych binarnych w kodzie.

. cokolwiek: Te pliki są tworzone na woluminach, które natywnie nie obsługują pełnej charakterystyki plików HFS (np. woluminy ufs, pliki Windows, itp.) Kiedy plik Mac jest kopiowany na taki wolumin, jego widelec danych jest przechowywany pod zwykłą nazwą pliku, a dodatkowe informacje HFS (widelec zasobów, kody typów i twórców itp.) Są przechowywane w drugim pliku (w formacie AppleDouble), o nazwie zaczynającej się od „. ”. (Pliki te są oczywiście niewidoczne dla OS-X, ale nie dla innych systemów operacyjnych; może to czasami być denerwujące ...)

Spcaeyob
źródło
1

Oto mój powód:

przed:

var path = "D:\xxx\util.s"

co \ujest ucieczką, doszedłem do tego, używając analizy JS Codepena .

po:

var path = "D:\\xxx\\util.s"

i błąd naprawiony

Miao1007
źródło
0

Miałem ten sam problem i tak się stało, ponieważ nacisnąłem klawisz Enter podczas dodawania kodu w ciągu tekstowym.

Ponieważ był to długi ciąg tekstu, chciałem to wszystko zobaczyć bez konieczności przewijania w edytorze tekstu, jednak naciśnięcie klawisza Enter dodawało niewidoczny znak do ciągu, co było nielegalne. Użyłem Sublime Text jako mojego edytora.

Jordan Davis
źródło
0

Zmieniłem wszystkie obszary kosmiczne na & nbsp, tak po prostu i zadziałało bez problemu.

val.replace („”, „& nbsp”);

Mam nadzieję, że to komuś pomoże.

Erdogan
źródło
0

Dodam jeszcze jedną odpowiedź do stosu. Ten problem może się zdarzyć również z powodu kodowania. Chcesz, aby kodowanie utf8 było bezpieczne. Niektóre edytory domyślnie używają utf16, co może powodować problemy. Jednym szybkim sposobem na przetestowanie tego jest, na przykład w kodzie VS, po prostu odtworzenie tej samej zawartości, ale użycie lokalnego edytora vscode do utworzenia pliku. Mam nadzieję, że to pomaga niektórym.

rezeli
źródło