Không có nguyên nhân có thể nhìn thấy đối với mã thông báo không mong đợi


270

Tôi đang gặp lỗi JavaScript này trên bảng điều khiển của mình:

Cú pháp không được khai báoGiá lỗi: Mã thông báo bất thường ILLEGAL

Đây là mã của tôi:

var foo = 'bar';​

Nó rất đơn giản, như bạn có thể thấy. Làm thế nào nó có thể gây ra một lỗi cú pháp?


9
Đối với những người đọc trong tương lai: nếu bạn gặp phải lỗi này khi sử dụng Vagrant - câu trả lời này cũng có thể hữu ích: stackoverflow.com/questions/9479117/ chủ
OZ_

Trong trường hợp bạn đang gặp phải điều này trong WordPress, hãy liệt kê các tập lệnh từ hàm.php. Tôi đã có một mẫu cụ thể nơi tôi đang gọi cho JS trực tiếp từ mẫu. Việc chuyển sang một enqueue có điều kiện trong wp_head hoặc wp_footer đã giải quyết điều này.
Alpesh Shah

7
Lưu ý của người điều hành: Tôi đã xóa một loạt các câu trả lời ở đây mà không thực sự trả lời câu hỏi. Đây không phải là, tôi nhắc lại không , một nơi để liệt kê mọi điều có thể bạn có thể làm trong JavaScript sẽ dẫn đến lỗi này. Câu hỏi có một tình huống rất cụ thể không liên quan đến bất kỳ tình huống nào và tất cả những ví dụ đó chỉ đơn giản là không trả lời câu hỏi.
phim hoạt hình

3
Wow, cảnh sát SO đã có một ngày thực địa với câu hỏi này. May mắn thay, một số thông tin liên quan vẫn còn hiển thị trong các câu trả lời đã bị xóa.
cdonner

Câu trả lời:


493

Lỗi

Khi mã được phân tích cú pháp bởi trình thông dịch JavaScript, nó sẽ bị chia thành các phần được gọi là "mã thông báo". Khi mã thông báo không thể được phân loại thành một trong bốn loại mã thông báo cơ bản , nó sẽ được gắn nhãn "MINH HÓA" trên hầu hết các triển khai và lỗi này được đưa ra.

Ví dụ, lỗi tương tự được nêu ra nếu bạn cố chạy tệp js với @ký tự giả mạo , dấu ngoặc nhọn bị đặt sai, dấu ngoặc, "dấu ngoặc kép thông minh", dấu ngoặc đơn không được đặt đúng (vd this.run('dev1)), v.v.

Rất nhiều tình huống khác nhau có thể gây ra lỗi này. Nhưng nếu bạn không có bất kỳ lỗi cú pháp rõ ràng hoặc ký tự bất hợp pháp, nó có thể được gây ra bởi một ký tự bất hợp pháp vô hình . Đó là những gì câu trả lời này là về.

Nhưng tôi không thể thấy bất cứ điều gì bất hợp pháp!

Có một ký tự vô hình trong mã, ngay sau dấu chấm phẩy. Đó là ký tự U+200Bkhông gian độ rộng Unicode (hay còn gọi là ZWSPthực thể HTML ​). Ký tự đó được biết là gây ra Unexpected token ILLEGALlỗi cú pháp JavaScript.

Và nó đến từ đâu?

Tôi không thể chắc chắn, nhưng đặt cược của tôi là vào jsfiddle . Nếu bạn dán mã từ đó, rất có thể bao gồm một hoặc nhiều U+200Bký tự. Có vẻ như công cụ sử dụng ký tự đó để điều khiển gói từ trên chuỗi dài.

CẬP NHẬT 2013-01-07

Sau bản cập nhật jsfiddle mới nhất , giờ đây nó hiển thị ký tự dưới dạng một chấm đỏ giống như codepen. Rõ ràng , nó cũng không U+200Btự chèn các ký tự nữa, vì vậy vấn đề này sẽ ít xảy ra hơn kể từ bây giờ.

CẬP NHẬT 2015/03/17

Vagrant đôi khi cũng gây ra vấn đề này, do lỗi trong VirtualBox . Giải pháp, theo bài đăng trên blog này là đặt sendfile off;trong cấu hình nginx của bạn hoặc EnableSendfile Offnếu bạn sử dụng Apache.

Cũng có báo cáo rằng mã được dán từ các công cụ dành cho nhà phát triển Chrome có thể bao gồm ký tự đó, nhưng tôi không thể sao chép mã đó với phiên bản hiện tại (22.0.1229.79 trên OSX).

Làm thế nào tôi có thể phát hiện ra nó?

Nhân vật là vô hình, làm sao chúng ta biết nó ở đó? Bạn có thể yêu cầu biên tập viên của bạn hiển thị các nhân vật vô hình. Hầu hết các trình soạn thảo văn bản có tính năng này. Vim, ví dụ, hiển thị chúng theo mặc định và ZWSPhiển thị dưới dạng <u200b>. Bạn cũng có thể gỡ lỗi trực tuyến: jsbin hiển thị ký tự dưới dạng một chấm đỏ trên các bảng mã của nó (nhưng dường như xóa nó sau khi lưu và tải lại trang). CodePen.io cũng hiển thị nó dưới dạng dấu chấm và giữ nó ngay cả sau khi lưu.

Các vấn đề liên quan

Nhân vật đó không phải là một cái gì đó xấu, nó thực sự có thể khá hữu ích. Ví dụ này trên Wikipedia cho thấy cách nó có thể được sử dụng để kiểm soát nơi một chuỗi dài sẽ được quấn vào dòng tiếp theo. Tuy nhiên, nếu bạn không biết về sự hiện diện của nhân vật trong lần đánh dấu của mình, điều đó có thể trở thành một vấn đề. Nếu bạn có chuỗi bên trong chuỗi (ví dụ: nodeValuephần tử DOM không có nội dung hiển thị), bạn có thể mong đợi chuỗi đó trống, trong khi thực tế thì không (ngay cả sau khi áp dụng String.trim).

ZWSPcũng có thể khiến khoảng trắng thêm được hiển thị trên trang HTML, ví dụ như khi nó được tìm thấy giữa hai <div>yếu tố (như đã thấy trong câu hỏi này ). Trường hợp này thậm chí không thể tái tạo trên jsfiddle, vì nhân vật bị bỏ qua ở đó.

Một vấn đề tiềm ẩn khác: nếu mã hóa của trang web không được nhận dạng là UTF-8, thì ký tự thực sự có thể được hiển thị ( ​ví dụ như trong latin1).

Nếu ZWSPcó trên mã CSS (mã nội tuyến hoặc biểu định kiểu bên ngoài), các kiểu cũng không thể được phân tích cú pháp đúng cách, vì vậy một số kiểu không được áp dụng (như đã thấy trong câu hỏi này ).

Đặc tả ECMAScript

Tôi không thể tìm thấy bất kỳ đề cập nào đến nhân vật cụ thể đó trên Đặc tả ECMAScript (phiên bản 35.1 ). Phiên bản hiện tại đề cập đến các ký tự tương tự ( U+200CU+200D) trên Phần 7.1 , cho biết chúng nên được coi là IdentifierParts khi "bên ngoài các bình luận, chuỗi ký tự và các biểu thức chính quy". Những ký tự đó có thể, ví dụ, là một phần của tên biến (và var x\u200c;thực sự hoạt động).

Mục 7.2 liệt kê các ký tự khoảng trắng hợp lệ (như tab, dấu cách, dấu cách, v.v.) và đề cập một cách mơ hồ rằng bất kỳ dấu tách không gian Unicode Unicode nào khác (danh mục Zs phạm) nên được coi là khoảng trắng. Tôi có lẽ không phải là người tốt nhất để thảo luận về thông số kỹ thuật về vấn đề này, nhưng dường như tôi U+200Bnên coi đó là khoảng trắng theo đó, trong thực tế, việc triển khai (ít nhất là Chrome và Firefox) dường như coi chúng là điều bất ngờ mã thông báo (hoặc một phần của một), gây ra lỗi cú pháp.


codepen.io cũng xuất hiện để hiển thị ký tự này. VIM và VI, notepad ++ cũng hiển thị nó.
rlemon

Cảm ơn @rlemon, đã thêm một ví dụ CodePen vào câu trả lời. Trang web đẹp, tôi không biết về nó.
bfavaretto

Gặp phải vấn đề này trong khi sao chép / dán mã cho lớp testTwo từ câu hỏi SO này bằng Chromium. Rõ ràng, trình phân tích cú pháp đã bóp nghẹt cú pháp tô sáng cú pháp của functiontừ khóa, ẩn trong Vim cho đến khi tôi làm nổi bật nó bằng phương pháp FAQ "Đánh dấu tất cả các ký tự không in được". Ahh thật tuyệt nếu có cách chỉ sao chép ký tự trong phạm vi 32..127 (nhưng có lẽ có một ứng dụng cho điều đó :))
ack

1
@bfavaretto, chỉ trong đoạn mã trong chế độ chỉnh sửa. Không phải trong cơ thể của câu hỏi, nên đã đề cập đến điều này. (Đã thử nghiệm trên Chrome 43.0.2357.124 m)
Fernando Leal

1
Nhiều trình soạn thảo văn bản cho phép chuyển đổi mã hóa ký tự của một tệp. Điều này cực kỳ hữu ích để tìm các nhân vật vi phạm như thế này. Giải pháp của tôi là tạm thời chuyển từ UTF-8 sang mã hóa ANSI, xóa các ký tự không hợp lệ, sau đó chuyển lại. Tôi đã sử dụng phần mềm miễn phí Notepad ++ trên Windows. EDIT: Hóa ra tôi đã bỏ lỡ tùy chọn Notepad ++ cho "Hiển thị tất cả các ký tự". Kết quả tương tự, ít rắc rối hơn: D
mbargiel 22/03/2016

64

Tại sao bạn tìm kiếm vấn đề này vào mã của bạn? Thậm chí, nếu nó được sao chép.

Nếu bạn có thể thấy, chính xác những gì xảy ra sau khi lưu tệp trong thư mục được đồng bộ hóa - bạn sẽ thấy một cái gì đó giống như *****ở cuối tệp. Nó hoàn toàn không liên quan đến mã của bạn.

Giải pháp.

Nếu bạn đang sử dụng nginxtrong hộp vagrant - thêm vào cấu hình máy chủ:

sendfile off;

Nếu bạn đang sử dụng apachetrong hộp vagrant - thêm vào cấu hình máy chủ:

EnableSendfile Off;

Nguồn của sự cố: Lỗi VirtualBox


6
Bạn thực sự đã cứu ngày của tôi. Tôi đã vật lộn với Nginx + Vagrant trong cả một buổi tối, và điều này đã giải quyết nó.
fradeve

2
Đã không mong đợi điều này là câu trả lời đúng (cho tôi) nhưng nó đã được, cảm ơn rất nhiều.
Charlotte

2
Trên thực tế, nó đã ngừng hoạt động. Sau đó, một lần nữa, có nhiều lớp liên kết tượng trưng đang diễn ra ở đây để tôi hoàn tác những gì tôi có thể.
Charlotte

Cảm ơn - Tôi đã ở trong một hộp mơ hồ với nginx. Tôi cũng đã thấy vấn đề này trên các thiết lập Apache tương tự.
Cameron

cho apache: EnableSendfile Off
jamlee

7

Điều này cũng có thể xảy ra nếu bạn sao chép mã từ một tài liệu khác (như PDF) vào bảng điều khiển của bạn và cố gắng chạy nó.

Tôi đã cố chạy một số mã ví dụ từ một cuốn sách Javascript mà tôi đang đọc và thật ngạc nhiên khi nó không chạy trong bảng điều khiển.

Rõ ràng, sao chép từ PDF giới thiệu một số ký tự bất ngờ, bất hợp pháp và vô hình vào mã.


5

Tôi gặp vấn đề tương tự trên máy mac của mình và thấy rằng đó là do máy Mac đã thay thế các trích dẫn tiêu chuẩn bằng các trích dẫn xoăn là các ký tự javascript bất hợp pháp.

Để khắc phục điều này, tôi đã phải thay đổi cài đặt trên mac System Preferences => Bàn phím => Văn bản (tab) bỏ chọn sử dụng dấu ngoặc kép và dấu gạch ngang thông minh (mặc định đã được chọn).


5

Tôi đã gặp lỗi này trong chrome khi tôi có một chuỗi bị lỗi sau dòng mà lỗi đã chỉ ra. Sau khi đóng chuỗi, lỗi đã biến mất.

Ví dụ có lỗi:

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>";

Ví dụ không có lỗi:

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

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

2
Tôi đã phải chạy một khác biệt trên hai ví dụ của bạn để tìm ra sự khác biệt, và một khi tôi đã làm ngay lập tức tôi đã tìm ra vấn đề của riêng tôi.
Ben Harold

3

Nếu bạn đang chạy một thiết lập nginx + uwsgi thì vấn đề chính là lỗi hộp ảo với tệp gửi như được đề cập trong một số câu trả lời. Tuy nhiên, để giải quyết nó, bạn phải vô hiệu hóa sendfile trong cả nginx và uwsgi.

  1. Trong nginx.conf sendfile tắt

  2. ứng dụng / cấu hình uwsgi --disable-sendfile


2

Khi chạy OS X, hệ thống tệp sẽ tạo ra các nhánh ẩn của tất cả các tệp của bạn, nếu chúng nằm trên ổ cứng không hỗ trợ HFS +. Điều này đôi khi có thể (xảy ra với tôi ngay bây giờ) dẫn đến công cụ JavaScript của bạn cố gắng chạy ngã ba dữ liệu thay vì mã mà bạn dự định chạy. Khi điều này xảy ra, bạn cũng sẽ nhận được

SyntaxError: Unexpected token ILLEGAL

bởi vì ngã ba dữ liệu của tệp của bạn sẽ chứa ký tự Unicode U + 200B. Xóa tệp ngã ba dữ liệu sẽ làm cho tập lệnh của bạn chạy mã thực tế, dự định của bạn, thay vì một ngã ba dữ liệu nhị phân của mã.

. sao cũng được: Những tệp này được tạo trên các tập không hỗ trợ đầy đủ các đặc điểm của tệp HFS (ví dụ: khối lượng ufs, tệp Windows, v.v.). Khi tệp Mac được sao chép vào một ổ đĩa như vậy, ngã ba dữ liệu của nó được lưu trữ dưới tên thông thường của tệp và thông tin HFS bổ sung (ngã ba tài nguyên, mã loại & mã tạo, v.v.) được lưu trữ trong tệp thứ hai (ở định dạng AppleDouble), với một tên bắt đầu bằng ". ". (Tất nhiên, các tệp này là vô hình khi có liên quan đến OS-X, nhưng không liên quan đến các hệ điều hành khác; điều này đôi khi có thể gây phiền nhiễu ...)


1

Đây là lý do của tôi:

trước:

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

đó \ulà một lối thoát, tôi đã tìm ra nó bằng cách sử dụng phân tích JS của Codepen .

sau:

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

và lỗi đã được sửa


0

Tôi gặp vấn đề tương tự và nó xảy ra vì tôi đã nhấn phím enter khi thêm mã vào chuỗi văn bản.

Bởi vì đó là một chuỗi văn bản dài mà tôi muốn xem tất cả mà không cần phải cuộn trong trình soạn thảo văn bản của mình, tuy nhiên nhấn enter đã thêm một ký tự vô hình vào chuỗi không hợp lệ. Tôi đã sử dụng Sublime Text làm biên tập viên của mình.


0

Tôi đã thay đổi tất cả các vùng không gian thành & nbsp, giống như vậy và nó hoạt động mà không gặp vấn đề gì.

val.replace ("", "& nbsp");

Tôi hi vọng nó giúp ích cho ai đó.


0

Tôi sẽ thêm một câu trả lời cho đống. Vấn đề này cũng có thể xảy ra vì mã hóa. Bạn muốn mã hóa utf8 ở bên an toàn. Một số trình soạn thảo theo mặc định sử dụng utf16 có thể gây ra sự cố. Một cách nhanh chóng để kiểm tra điều này, ví dụ như trong mã VS, chỉ cần tạo lại cùng một nội dung nhưng sử dụng trình soạn thảo cục bộ của vscode để tạo tệp. Hy vọng điều này sẽ giúp một số.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.