Javascript 调用number-literal的成员函数

Javascript 调用number-literal的成员函数,javascript,Javascript,我试图调用文字函数,但我有奇怪的行为 考虑返回true的代码 23 === (23) 当我写的时候,试试下面的方法 (23).toFixed(2) 我得到了预期的结果\u 23.00\u但是当我尝试23.toFixed(2)时,我得到了这个错误 SyntaxError:意外标记非法 JavaScript如何计算无法理解的表达式,为什么会出现此错误?与Ruby(例如)不同,JavaScript解析器将数字后面的视为数字的一部分。因此解析器可以看到标记: 23.toFixed(2) 这是一

我试图调用文字函数,但我有奇怪的行为

考虑返回
true
的代码

   23 === (23)
当我写的时候,试试下面的方法

(23).toFixed(2)
我得到了预期的结果
\u 23.00\u
但是当我尝试
23.toFixed(2)
时,我得到了这个错误

SyntaxError:意外标记非法

JavaScript如何计算无法理解的表达式,为什么会出现此错误?

与Ruby(例如)不同,JavaScript解析器将数字后面的
视为数字的一部分。因此解析器可以看到标记:

23.
toFixed
2

这是一个语法错误,因为紧跟在浮点数后面的单词
toFixed
没有意义。接受此语法的Ruby等语言将看到以下标记:

23
toFixed
2
考虑:

5.
是浮点文本
5.
还是整数
5
后跟一个点?你不知道;这是模棱两可的。JavaScript采用前一种观点。在JavaScript的视图中,您得到了一个浮点文本,后跟一个标识符(然后后跟一个左括号、数字和一个右括号)

有些人用两点来解决这个问题:

23..toFixed(2)
由于浮点文字只能有一个小数点,所以另一个点是文字点标记。

答案在各个方面都是正确的,但是,我想从抽象角度讲一点:让我们看看根据javascript规范到底发生了什么

该规范定义了数字文字。我们可以看到:

DecimalLiteral ::
    DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
    . DecimalDigits ExponentPart(opt)
    DecimalIntegerLiteral ExponentPart(opt)

DecimalIntegerLiteral ::
    0 
    NonZeroDigit DecimalDigits(opt)
小数位数
是一个数字,是一组十进制数字,后面可能跟一个点,后面可能跟其他数字(例如,所有数字后面都可以跟一个指数,
e12
)。换句话说,
42.
是合法的,等于
42
3e2
等于
300

请注意,如果我们有一个点,我们要么期望它后面跟着更多的数字/指数,要么什么也不跟。然而,这是重要的部分,点是数字的一部分。记住这一点,我们来看看如何处理点运算符,
obj.prop

描述成员访问的点和括号符号:

MemberExpression . IdentifierName
CallExpression
用于函数调用,我们不关心函数调用。请注意我们是如何期待一个
成员表达式
(可以是
小数位数
——但不要相信我的话,看看我是否正确)

看到那个小点了吗?跳到前面说“好吧,这里的方案中有一个点……而
4.foo
中有一个点……那么为什么会有错误呢?”这是合乎逻辑的。唉,我的假想朋友,我用他来解释这些句子,你忘了
小数位数是什么样子了!让我们看两个例子,看看会发生什么

42.foo
^
插入符号代表我们所处的角色。到目前为止,我们已经进入了
小数位数/DecimalIntegerLiteral/non-zerodigital
(这真是太多了)。让我们转到下一个角色:

42.foo
 ^
仍然是数字的一部分,是完全有效的
小数位数

42.foo
  ^
好的,我们没有了
DecimalIntegerLiteral
部分。以下是该方案的相同图表:

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
                      ^
MemberExpression . IdentifierName
      ^
所以我们在一个点上,这是一个数字的一个完全有效的部分。现在,我们将其作为数字的一部分使用,然后继续:

42.foo
   ^
f
既不是小数位数的一部分,也不是指数部分的一部分,我们现在没有了。那么…现在怎么办?那是什么?这不是任何事情的一部分。也许是一个属性访问器?让我们来看一下这个方案:

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
                      ^
MemberExpression . IdentifierName
      ^
我们肯定是在
MemberExpression
上,但后面没有一个点-这个点已经是数字的一部分了。我们遇到了一个语法错误:我们停止执行并抛出它。希望你不是住在玻璃房子里

希望你现在明白为什么
42..foo
有效了。一旦我们离开了
成员表达式
,我们将面临另一个点:

              42..foo
                 ^
MemberExpression . IdentifierName
                 ^
然后是一个完全合法的
标识名

当然,还有其他几种方法可以将点与数字分开。如您所示,一种方法是将文字括在括号中:
(42).foo
。当我们到达圆括号的末尾时,我们就离开了
MemberExpression
,并且准时到达。另一种方法是插入一个空格:
42.foo
,因为空格不能是数字的一部分,而且对于解析器来说是中性的,所以不会引发错误