“意外的令牌非法”没有明显的原因

IT技术 javascript syntax-error illegal-characters
2021-01-21 10:14:51

我在控制台上收到此 JavaScript 错误:

未捕获的语法错误:意外的令牌非法

这是我的代码:

var foo = 'bar';​

如您所见,这非常简单。它怎么会导致语法错误?

6个回答

错误

当 JavaScript 解释器解析代码时,它会被分解成称为“令牌”的部分。当令牌无法归类为四种基本令牌类型之一时,它会在大多数实现中被标记为“非法”,并抛出此错误。

例如,如果您尝试运行带有流氓@字符、错位的大括号、括号、“智能引号”、未正确括起来的单引号(例如this.run('dev1))等的 js 文件,则会引发相同的错误

许多不同的情况都可能导致此错误。但是如果你没有任何明显的语法错误或非法字符,它可能是由一个不可见的非法字符引起的这就是这个答案的内容。

但我看不出有什么违法的!

代码中有一个不可见的字符,就在分号之后。它是UnicodeU+200B零宽度空格字符(又名ZWSP,HTML 实体​)。已知该字符会导致Unexpected token ILLEGALJavaScript 语法错误。

它是从哪里来的?

我不能肯定,但我的赌注是jsfiddle如果您从那里粘贴代码,则很可能包含一个或多个U+200B字符。该工具似乎使用该字符来控制长字符串的自动换行。

更新 2013-01-07

在最新的jsfiddle 更新之后它现在像 codepen 一样将角色显示为红点显然,它也U+200B不再单独插入字符,所以从现在开始这个问题应该不那么频繁了。

更新 2015-03-17

由于VirtualBox 中的错误,Vagrant有时似乎也会导致此问题根据这篇博文,解决方案sendfile off;在您的 nginx 配置中进行设置,或者EnableSendfile Off如果您使用 Apache。

报道,从 Chrome 开发人员工具粘贴的代码可能包含该字符,但我无法使用当前版本(OSX 上的 22.0.1229.79)重现该字符。

我怎样才能发现它?

角色是隐形的,我们怎么知道它在那里?您可以要求编辑器显示不可见字符。大多数文本编辑器都有这个功能。例如,Vim 默认显示它们,并且ZWSP显示为<u200b>. 您也可以在线调试它:jsbin在其代码窗格中将字符显示为红点(但似乎在保存并重新加载页面后将其删除)。CodePen.io 也将它显示为一个点,并在保存后保留它。

相关问题

这个角色并不是什么坏东西,它实际上非常有用。维基百科上的这个例子演示了如何使用它来控制长字符串应该在哪里换行到下一行。但是,如果您不知道该角色出现在您的标记中,则可能会成为一个问题。如果您将它放在一个字符串中(例如,nodeValue没有可见内容的 DOM 元素的 ),您可能希望这样的字符串为空,而实际上它不是(即使在 apply 之后String.trim)。

ZWSP也可能导致在 HTML 页面上显示额外的空白,例如,当它位于两个<div>元素之间时(如本问题所示)。这种情况甚至无法在 jsfiddle 上重现,因为在那里忽略了该字符。

另一个潜在问题:如果网页的编码未被识别为 UTF-8,则该字符可能会实际显示(例如​在 latin1 中)。

如果ZWSPCSS 代码(内联代码或外部样式表)中存在样式,则样式也无法正确解析,因此某些样式无法应用(如本问题所示)。

ECMAScript 规范

我在 ECMAScript 规范(版本35.1)中找不到对该特定字符的任何提及当前版本第 7.1 节中提到了类似的字符 ( U+200Cand U+200D) ,其中说当“在注释、字符串文字和正则表达式文字之外”时,它们应该被视为s。例如,这些字符可能是变量名称的一部分(并且确实有效)。IdentifierPartvar x\u200c;

第 7.2 节列出了有效的空白字符(例如制表符、空格、不间断空格等),并含糊地提到任何其他 Unicode“空格分隔符”(类别“Zs”)都应被视为空白。在这方面,我可能不是讨论规范的最佳人选,但在我看来,U+200B应该将其视为空白,而实际上实现(至少 Chrome 和 Firefox)似乎将它们视为意外令牌(或其中的一部分),导致语法错误。

谢谢@rlemon,在答案中添加了一个 CodePen 示例。不错的网站,我不知道。
2021-03-14 10:14:51
@bfavaretto,仅在编辑模式下的代码片段中。不在问题的正文中,应该提到这一点。(在 Chrome 43.0.2357.124 m 上测试)
2021-03-20 10:14:51
使用 Chromium这个 SO 问题复制/粘贴 testTwo 类的代码时遇到了这个问题显然,解析器阻塞了function关键字的语法突出显示,这在 Vim 中是不可见的,直到我使用“突出显示所有不可打印字符”常见问题解答方法突出显示它。啊,如果有一种方法可以只复制 32..127 范围内的字符,那就太好了(但可能有一个应用程序:))
2021-03-22 10:14:51
codepen.io 似乎也显示了这个字符。VIM 和 VI,notepad++ 也显示它。
2021-04-05 10:14:51
许多文本编辑器允许切换文件的字符编码。这对于找到这些冒犯性的角色非常有用。我的解决方案是暂时从 UTF-8 切换到 ANSI 编码,删除无效字符,然后切换回来。我在 Windows 上使用了免费软件 Notepad++。编辑:结果我错过了“显示所有字符”的 Notepad++ 选项。相同的结果,更少的麻烦:D
2021-04-07 10:14:51

为什么你在你的代码中寻找这个问题?甚至,如果它是复制粘贴的。

如果你能看到,在同步文件夹中保存文件后究竟发生了什么 - 你会*****在文件末尾看到类似的东西它根本与您的代码无关。

解决方案。

如果您nginx在 vagrant box中使用- 添加到服务器配置:

sendfile off;

如果您apache在 vagrant box中使用- 添加到服务器配置:

EnableSendfile Off;

问题来源:VirtualBox Bug

你真的救了我的一天。我在 Nginx + Vagrant 上挣扎了整整一个晚上,这解决了它。
2021-03-11 10:14:51
实际上,它停止了工作。再说一次,这里有多层符号链接在起作用,所以我只是解除了我能做的。
2021-03-14 10:14:51
对于 apache:启用发送文件关闭
2021-03-17 10:14:51
不要期望这是正确的答案(对我来说),但它是,非常感谢。
2021-03-21 10:14:51
谢谢 - 我和 nginx 一起在一个流浪的盒子里。我也在类似的 Apache 设置中看到了这个问题。
2021-04-05 10:14:51

如果您将代码从另一个文档(如 PDF)复制到控制台并尝试运行它,也可能会发生这种情况。

我试图从我正在阅读的一本 Javascript 书中运行一些示例代码,但很惊讶它没有在控制台中运行。

显然,从 PDF 复制会在代码中引入一些意外的、非法的和不可见的字符。

我在我的 mac 上遇到了同样的问题,发现这是因为 Mac 用非法 javascript 字符的curl引号替换了标准引号。

为了解决这个问题,我不得不更改我的 mac 系统偏好设置=>键盘=>文本(标签)取消选中使用智能引号和破折号(默认被选中)。

当我在错误指向的行之后有一个未终止的字符串时,我在 chrome 中遇到了这个错误。关闭字符串后,错误消失了。

错误示例:

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

没有错误的例子:

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

jQuery('#someDiv').innerHTML = file.name + " (" + formatSize(file.size) + ") "
    + "<a href=\"javascript: something('"+file.id+"');\">Error was here</a>";
我不得不在你的两个例子上运行一个差异来找出差异,一旦我这样做了,我立即找出了我自己的问题。
2021-03-23 10:14:51