"Unexpected token ILLEGAL" 的出现原因不明。

274

在我的控制台上出现了JavaScript错误:

Uncaught SyntaxError: Unexpected token ILLEGAL

这是我的代码:

var foo = 'bar';​

你可以看到,它非常简单。那么它怎么会引起语法错误呢?


9
供未来读者参考:如果您在使用Vagrant时遇到此错误,这个回答也可能会有所帮助:https://dev59.com/qGkx5IYBdhLWcg3wCf8q - OZ_
如果您在WordPress中遇到此问题,请从functions.php中排队脚本。我有一个特定的模板,我直接从模板中调用JS。在wp_head或wp_footer中切换到条件排队可以解决此问题。 - Alpesh Shah
8
主持人的提示: 我删除了一些并不实际回答问题的答案。这里不是列举 JavaScript 中可能导致此错误的每个可能性的地方。该问题具有非常特定的情况,不涉及这些场景中的任何一种,所有这些示例都回答问题。 - animuson
4
哇,SO(指Stack Overflow)的警察们对这个问题大做文章。幸运的是,一些相关信息仍然可以在被删除的回答中看到。 - cdonner
11个回答

496

错误

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

如果你尝试运行带有流氓@字符、错放的花括号、方括号、"智能引号"、未正确封闭的单引号(例如this.run('dev1))等js文件,也会引发同样的错误。

许多不同的情况都可能导致这个错误。但如果你没有明显的语法错误或非法字符,那么可能是由于一个不可见的非法字符引起的。这就是本答案所涉及的内容。

但我看不到任何非法字符!

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

那么这个字符从哪里来的呢?

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

2013年1月7日更新

在最新的jsfiddle更新之后,现在显示为红点,就像codepen一样显然,它也不再自动插入U+200B字符,所以这个问题从现在开始应该会更少发生。

2015年3月17日更新

Vagrant似乎有时也会引起这个问题,因为VirtualBox存在一个错误。根据这篇博客文章的解决方案,在你的nginx配置中设置sendfile off;,或者如果你使用Apache,则设置EnableSendfile Off

也有报道称从Chrome开发者工具中粘贴的代码可能包含该字符,但我无法在当前版本(OSX上的22.0.1229.79)中复现。

如何发现它?

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

相关问题

这个字符并不是什么坏东西,实际上它可以非常有用。维基百科上的这个例子演示了如何使用它控制长字符串应在下一行换行的位置。然而,如果您没有意识到标记中存在该字符,它可能会成为一个问题。如果您将其放在一个字符串中(例如,一个没有可见内容的DOM元素的 nodeValue ),您可能期望这种字符串为空,但实际上它不是空的(即使应用了 String.trim 后)。

ZWSP也会导致在HTML页面上显示额外的空白,例如当它出现在两个<div>元素之间时(如此问题所示)。在jsfiddle上即使出现该字符,也不会重现此情况,因为该字符在那里被忽略。

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

如果CSS代码(内联代码或外部样式表)中存在ZWSP,则样式也可能无法正确解析,因此某些样式不会应用(如this question所示)。

ECMAScript规范

我在 ECMAScript 规范中(版本 35.1)没有找到关于那个特定字符的任何提及。当前版本在第7.1节中提到了类似的字符(U+200CU+200D),该节表示当“不在注释、字符串文字和正则表达式文字之内”时,它们应被视为IdentifierPart。这些字符可能是变量名的一部分(例如,var x\u200c;确实可以工作)。

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


在使用Chromium从this SO question复制/粘贴testTwo类的代码时,遇到了这个问题。显然,解析器无法处理function关键字的语法高亮,在Vim中是看不见的,直到我使用“突出显示所有不可打印字符”的FAQ方法将其突出显示。如果只复制32..127范围内的字符,那就太好了(但可能有一个应用程序可以做到这一点:))。 - ack
我在Vim中使用wordwrap的数组时遇到了这个错误。谢谢! - Matt
@bfavaretto,问题中的代码片段也会将字符显示为红点。 - Fernando Leal
1
@bfavaretto,只有在编辑模式下的代码片段中。不应该出现在问题正文中。(已在Chrome 43.0.2357.124 m上测试) - Fernando Leal
1
许多文本编辑器允许切换文件的字符编码。这对于查找像这样的有问题的字符非常有用。我的解决方案是暂时从UTF-8切换到ANSI编码,删除无效字符,然后再切换回来。我在Windows上使用了免费软件Notepad ++。编辑:事实证明,我错过了Notepad ++的“显示所有字符”选项。同样的结果,更少的麻烦:D - mbargiel
显示剩余11条评论

64

为什么要在代码中寻找这个问题呢?即使是复制粘贴的。

如果您可以看到同步文件夹中保存文件后发生的情况-您将会看到文件末尾类似于 ***** 的东西。这与您的代码无关。

解决方法。

如果您在vagrant box中使用nginx,请将以下内容添加到服务器配置中:

sendfile off;

如果您在vagrant box中使用apache,请将以下内容添加到服务器配置文件:

EnableSendfile Off;

问题来源:VirtualBox Bug


6
你真的救了我的一天。我整个晚上都在与Nginx + Vagrant纠结,但这解决了问题。 - fradeve
2
没有 想到这是正确答案(对我来说),但它确实是,非常感谢。 - Belladonna
2
实际上,它停止工作了。然后,在这里有多个符号链接层起作用,所以我只是撤消了我能做的。 - Belladonna
谢谢 - 我在一个带有nginx的vagrant box中。我也在类似的Apache设置中看到了这个问题。 - Cameron
对于Apache服务器:启用Sendfile关闭 - jamlee
非常感谢!我以为这是gulp或webpack的问题。我从未想过这是vagrant的问题! - Andrey Ashgaliyev

7

如果你是从其他文档(如PDF)复制代码到控制台并尝试运行,也可能会出现这种情况。

我正在尝试运行一本我正在阅读的JavaScript书中的一些示例代码,但惊讶地发现它在控制台中无法运行。

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


5

我在我的Mac电脑上也遇到了同样的问题,后来发现是因为Mac电脑使用了弯引号替换标准引号,而这些弯引号是不合法的JavaScript字符。

要解决这个问题,我需要更改Mac电脑的设置。具体方法是:打开系统偏好设置 => 键盘 => 文本(tab) 取消“使用智能引号和破折号”(默认已选中)。


5

当我在错误指向的行后面有一个未终止的字符串时,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>";

2
我不得不在你的两个示例上运行diff来找出差异,一旦我找到了,我立即发现了自己的问题。 - Ben Harold

3
如果您正在运行Nginx + uWSGI的vagrant,则主要问题是Virtualbox bug,涉及发送文件,如某些回答中所述。但是,要解决此问题,您需要在Nginx和uWSGI中禁用sendfile。
  1. 在nginx.conf中 sendfile off

  2. uwsgi应用程序/配置 --disable-sendfile


2
当运行OS X时,文件系统会为基本上所有的文件创建隐藏的分支,如果它们在不支持HFS+的硬盘上。这有时会导致你的JavaScript引擎尝试运行数据分支而不是你打算运行的代码。当发生这种情况时,你也会收到


SyntaxError: Unexpected token ILLEGAL

因为您的文件的数据叉将包含Unicode U+200B字符。删除数据叉文件将使您的脚本运行实际的、预期的代码,而不是代码的二进制数据叉。

.无论如何:这些文件是在原生不支持完整HFS文件特征的卷上创建的(例如ufs卷,Windows文件共享等)。当Mac文件复制到这样的卷上时,它的数据叉存储在文件的常规名称下,并且其他HFS信息(资源叉、类型和创建者代码等)存储在第二个文件中(以AppleDouble格式),该文件名以“.”开头。(当然,这些文件在OS-X方面是不可见的,但对其他操作系统来说不是;这有时可能很烦人...)


1

这是我的原因:

之前:

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

\u 是一种转义字符,我通过使用Codepen的分析JS找到了答案。

之后:

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

并且错误已经修复


0

我打算再增加一个答案。这个问题可能是由于编码问题引起的。你需要使用utf8编码来确保安全。一些编辑器默认使用utf16,这可能会导致问题。测试这个问题的一种快速方法是,在VS code中,简单地重新创建相同的内容,但使用vscode的本地编辑器来创建文件。 希望这能帮到一些人。


0

我曾经遇到过同样的问题,这是因为我在文本字符串中添加代码时按下了回车键。

由于这是一长串文本,我想要在不滚动文本编辑器的情况下查看全部内容,但是按下回车键会向字符串中添加一个不可见字符,这是非法的。我使用的是Sublime Text编辑器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接