调用数字文字的成员函数

Beh*_*rsi 48 javascript

我试图调用文字函数,但我得到了奇怪的行为.

考虑这个返回的代码true.

   23 === (23)
Run Code Online (Sandbox Code Playgroud)

当我写作尝试以下.

(23).toFixed(2)
Run Code Online (Sandbox Code Playgroud)

我得到了预期的结果_23.00_但是当我尝试时23.toFixed(2)我得到了这个错误.

SyntaxError:意外的标记ILLEGAL

JavaScript如何评估无法理解的表达式以及为什么会出现此错误?

Zir*_*rak 59

Greg Hewgillicktoofay的答案在所有方面都是正确的,但是,我想要抽象一点,抽象明智:让我们看看根据javascript规范真正发生了什么.

规范的第7.8.3节定义了数字文字.我们可以看到以下内容:

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

DecimalIntegerLiteral ::
    0 
    NonZeroDigit DecimalDigits(opt)
Run Code Online (Sandbox Code Playgroud)

A DecimalLiteral,一个数字,是一串十进制数字,可能后跟一个点,后面可能跟着其他数字(例如,所有数字后面都可以跟一个指数e12).换句话说,42.是合法的,等于423e2等于300.

注意如果我们有一个点,我们要么预期它会跟随更多的数字/指数,或者后面没有任何数字.然而,这是重要的部分,点是数字的一部分.记住这一点,我们开始研究如何处理点运算符obj.prop.

第11.2.1节,属性访问器描述了成员访问的点和括号表示法:

MemberExpression . IdentifierName
Run Code Online (Sandbox Code Playgroud)

CallExpression用于函数调用,我们不关心.注意我们是如何期待的MemberExpression(这可能是DecimalLiteral- 但不要接受我的话,看看我是否正确).

看到那个小点?向前跳并说"好吧,这里的方案中有一个点4.foo...... 这里有一个点......所以为什么会有错误?" 唉,我用这些句子的假想朋友,你忘记了它的DecimalLiteral样子!让我们看看两个例子,看看会发生什么.

42.foo
^
Run Code Online (Sandbox Code Playgroud)

插入符代表我们所处的角色.到目前为止,我们在里面DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit(这是非常满口).让我们转到下一个角色:

42.foo
 ^
Run Code Online (Sandbox Code Playgroud)

仍然是数字的一部分,完全有效DecimalDigit.

42.foo
  ^
Run Code Online (Sandbox Code Playgroud)

好的,所以我们已经DecimalIntegerLiteral不在了.这是该计划的相同图表:

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
                      ^
Run Code Online (Sandbox Code Playgroud)

所以我们在一个点上,这是一个完全有效的数字部分.现在我们消耗它,作为数字的一部分,继续:

42.foo
   ^
Run Code Online (Sandbox Code Playgroud)

f既不是我们的一部分,DecimalDigits也不是ExponentPart我们现在的数字.所以现在怎么办?那是什么f?这不是任何事情的一部分.也许它是一个属性访问者?我们来看看这个方案:

MemberExpression . IdentifierName
      ^
Run Code Online (Sandbox Code Playgroud)

我们肯定在MemberExpression,但我们没有跟随它的点 - 该点已经是数字的一部分.我们遇到了一个语法错误:我们停止执行并抛出它.希望你不住在玻璃房子里.

希望你现在明白为什么42..foo有效.一旦我们离开了MemberExpression,我们将面对另一个点:

              42..foo
                 ^
MemberExpression . IdentifierName
                 ^
Run Code Online (Sandbox Code Playgroud)

其次是完全合法的IdentifierName.

当然,还有其他几种方法可以将点与数字分开.正如你所展示的那样,一种方法是在括号中包围文字:(42).foo.当我们到达括号结束时,我们已经离开了MemberExpression,并且在点上.另一种方法是插入一个空格:42 .foo,因为空格不能是数字的一部分,并且它对于解析器是中性的,所以它不会引发错误.


Gre*_*ill 34

与Ruby(例如)不同,Javascript解析器认为.后续数字是数字的一部分.所以解析器看到了令牌:

23. toFixed ( 2 )

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

23 . toFixed ( 2 )


ick*_*fay 23

考虑:

5.
Run Code Online (Sandbox Code Playgroud)

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

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

23..toFixed(2)
Run Code Online (Sandbox Code Playgroud)

由于浮点文字只能有一个小数点,另一个点是文字点标记.