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+200B
không gian độ rộng Unicode (hay còn gọi là ZWSP
thực thể HTML ​
). Ký tự đó được biết là gây ra Unexpected token ILLEGAL
lỗ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+200B
ký 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+200B
tự 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 Off
nế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à ZWSP
hiể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ụ: nodeValue
phầ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
).
ZWSP
cũ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 ZWSP
có 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 3 và 5.1 ). Phiên bản hiện tại đề cập đến các ký tự tương tự ( U+200C
và U+200D
) trên Phần 7.1 , cho biết chúng nên được coi là IdentifierPart
s 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+200B
nê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.