我试图调用文字函数,但我得到了奇怪的行为。
考虑这个返回的代码true
。
23 === (23)
当我写尝试以下。
(23).toFixed(2)
我得到了预期的结果_23.00_
,但是当我尝试时,23.toFixed(2)
我得到了这个错误。
SyntaxError:意外的令牌非法
JavaScript 如何评估无法理解的表达式,为什么会出现此错误?
我试图调用文字函数,但我得到了奇怪的行为。
考虑这个返回的代码true
。
23 === (23)
当我写尝试以下。
(23).toFixed(2)
我得到了预期的结果_23.00_
,但是当我尝试时,23.toFixed(2)
我得到了这个错误。
SyntaxError:意外的令牌非法
JavaScript 如何评估无法理解的表达式,为什么会出现此错误?
Greg Hewgill和icktoofay的答案在所有方面都是正确的,但是,我想在抽象方面稍微冷静一下:让我们看看根据 javascript 规范到底发生了什么。
规范的第 7.8.3 节定义了数字文字。我们可以看到以下内容:
DecimalLiteral ::
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
. DecimalDigits ExponentPart(opt)
DecimalIntegerLiteral ExponentPart(opt)
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits(opt)
ADecimalLiteral
是一个数字,是一串十进制数字,后面可能跟一个点,后面可能跟其他数字(e12
例如,所有数字后面都可以跟一个指数)。换句话说,42.
是合法的,等于42
并且3e2
等于300
。
请注意,如果我们有一个点,我们要么期望它后面跟着更多的数字/指数,要么后面什么也不跟。但是,这是重要的部分,点是数字的一部分。请记住这一点,因为我们要查看点运算符 ,obj.prop
是如何处理的。
第 11.2.1 节,属性访问器描述了成员访问的点和括号表示法:
MemberExpression . IdentifierName
CallExpression
用于函数调用,我们并不关心。请注意我们如何期待 a MemberExpression
(可以是DecimalLiteral
- 但不要相信我的话,看看我是否正确)。
看到那个小点了吗?向前跳并说“好吧,这里的方案中有一个点......并且......里面有一个点4.foo
......所以为什么会有错误?”是合乎逻辑的。唉,我在这些句子中使用的假设朋友,你忘记了它的DecimalLiteral
样子!让我们看两个例子,看看会发生什么。
42.foo
^
插入符号代表我们所在的角色。到目前为止,我们在里面DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit
(这是相当满口的)。让我们转到下一个字符:
42.foo
^
仍然是数字的一部分,一个完全有效的DecimalDigit
.
42.foo
^
好的,所以我们不在了DecimalIntegerLiteral
。这是该计划的相同图表:
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
^
所以我们在一个点上,它是一个数字的完全有效的部分。现在我们将它作为 number 的一部分使用,然后继续:
42.foo
^
f
既不是 的 一部分DecimalDigits
也 不是 的ExponentPart
,我们现在已经没有数字了。所以现在怎么办?那是什么f
?它不是任何东西的一部分。也许它是一个属性访问器?我们来看看方案:
MemberExpression . IdentifierName
^
我们肯定在 上MemberExpression
,但我们没有在它后面跟着一个点——那个点已经是数字的一部分。我们遇到了一个语法错误:我们停止执行并抛出它。希望你不要住在玻璃房子里。
希望现在你明白为什么42..foo
有效。一旦我们离开了MemberExpression
,我们将面临另一个问题:
42..foo
^
MemberExpression . IdentifierName
^
其次是完全合法的IdentifierName
。
当然,还有其他几种方法可以将点与数字分开。正如您所展示的,一种方法是将文字括在括号中:(42).foo
. 当我们到达括号末尾时,我们不在MemberExpression
, 并且在点上。另一种方法是插入一个空格:42 .foo
,因为空格不能是数字的一部分,而且它对解析器是中性的,所以它不会引发错误。
与 Ruby(例如)不同,Javascript 解析器将.
后面的数字视为数字的一部分。所以解析器看到了标记:
23.
toFixed
(
2
)
这是一个语法错误,因为toFixed
紧跟在浮点数后面的单词没有意义。像 Ruby 这样接受这种语法的语言会看到以下标记:
23
.
toFixed
(
2
)
考虑:
5.
那是浮点文字5.
还是整数5
后跟一个点?你不知道;这是模棱两可的。JavaScript 采用前一种观点。在 JavaScript 看来,您有一个浮点字面量,后跟一个标识符(然后是左括号、数字和右括号)。
有些人通过使用两个点来解决这个问题:
23..toFixed(2)
由于浮点文字只能有一个小数点,因此另一个点是文字点标记。