关键字和文字之间需要空格

Spaces required between keyword and literal

查看 UglifyJS2 的输出,我注意到文字和 in 运算符之间不需要 space(例如,'foo'in{foo:'bar'} 有效)。

然而,在使用 Chrome 的 DevTools 时,我注意到十六进制和二进制数字文字在 in 关键字之前需要一个 space:

Internet Explorer 对所有三个测试都返回 true,而 FireFox 48.0.1 对第一个测试抛出一个 SyntaxError (1in foo),但是字符串文字是可以的 ('1'in foo==true)。

似乎解析 JavaScript 应该没有问题,允许关键字紧挨着数字文字,但我在 ECMAScript 规范中找不到任何明确的规则(其中任何一个)。

进一步测试表明,Chrome 和 FireFox(IE11 不支持 for..of 循环)都允许像 for(var i of[1,2,3])... 这样的语句,并且 typeof"string" 在所有三个中都有效.

哪种行为是正确的?事实上,它是在我错过的某个地方定义的,还是所有这些效果都是每个浏览器解析器的特性造成的?

不是专家 - 我没有做过 JS 编译器,但做过其他的。

ecma-262.pdf有点模糊,但是很明显,像1 in foo这样的表达式应该被解析为3个输入元素,都是token。每个token是一个CommonToken (11.5);在这种情况下,我们得到 numericLiteralidentifierName(是的,in 是一个 identifierName)和 identifierName。解析 0b1 in foo 时也是如此(见 11.8.3).

那么,当你取出 WS 时会发生什么?它没有明确涵盖(据我所知),但它是编写词法分析器扫描最长字符序列(可能与您可能正在寻找的内容匹配)时的常见做法(在其他语言中)。第 11 节的介绍几乎完全是这样说的:

The source text is scanned from left to right, repeatedly taking the longest possible sequence of code points as the next input element.

因此,对于 0b1in foo,词法分析器经过 0b1,它匹配一个数字文字,然后到达 i,给出 0b1i,它不匹配任何东西.因此它将最长的匹配项 (0b1) 作为标记传递给解析器的其余部分,并在 i 处再次开始。它找到 n,然后是 WS,因此将 in 作为第二个标记传递,依此类推。

所以,基本上,奇怪的是,IE 看起来是正确的。

TL;DR 如果在这些情况下不需要空格,代码的解释方式将不会发生变化,但它是规范的一部分。

查看 source code of v8 that handles number literal parsing, it cites ECMA 262 § 7.8.3:

The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit.

NOTE For example:

3in

is an error and not the two input elements 3 and in.

这部分似乎与第7部分的介绍相矛盾。但是,打破该规则并允许解析3in似乎不​​会有任何问题。在某些情况下,文字和标识符之间不允许有空格会改变源代码的解析方式,但所有情况只会改变生成的错误。