50

リテラル関数を呼び出そうとしていますが、奇妙な動作が発生します。

を返すこのコードを検討してくださいtrue

   23 === (23)

私が書くときは、次のことを試してください。

(23).toFixed(2)

期待どおりの結果_23.00_が得られますが、試してみる23.toFixed(2)とこのエラーが発生します。

SyntaxError: 予期しないトークン ILLEGAL

JavaScript はこれを理解できない式をどのように評価し、なぜこのエラーが発生するのですか?

4

3 に答える 3

61

Greg Hewgillicktoofayによる回答はすべての点で正しいですが、抽象化に関して少し掘り下げたいと思います。JavaScript の仕様に従って実際に何が起こっているか見てみましょう。

仕様のセクション 7.8.3では、数値リテラルが定義されています。次のことがわかります。

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

DecimalIntegerLiteral ::
    0 
    NonZeroDigit DecimalDigits(opt)

A DecimalLiteral、数値は、10 進数の数字の集まりであり、その後にドットが続く可能性があり、その後に他の数字が続く可能性があります (たとえば、すべての後に指数が続く可能性がありe12ます)。言い換えると、42.は合法であり、 に等しく、 に42等しい3e2です300

ドットがある場合、その後にさらに数字/指数が続くか、何も続かないと予想されることに注意してください。ただし、これは重要な部分です。ドットは数字の一部です。ドット演算子 がどのようにobj.prop扱われるかを見ていく際に、このことを思い出してください。

セクション 11.2.1, プロパティ アクセサーでは、メンバー アクセスのドットとブラケットの表記について説明しています。

MemberExpression . IdentifierName

CallExpression気にしない関数呼び出し用です。どのように a が期待されているかに注意してくださいMemberExpression(これは a である可能性がありますがDecimalLiteral、私の言葉を鵜呑みにしないでください。私が正しいかどうかを見てください)。

あの小さな点が見えますか?4.foo先に進んで、「ここのスキームにドットがあります...そしてドットがあります...では、なぜエラーがあるのでしょうか?」と言うのは論理的です。悲しいかな、私がこれらの文で使用している架空の友人ですが、あなたは がどのようにDecimalLiteral見えるか忘れてしまいました! 2 つの例を見て、何が起こるか見てみましょう。

42.foo
^

キャレットは、現在の文字を表します。これまでのところ、私たちは中にいますDecimalLiteral / DecimalIntegerLiteral / NonZeroDigit(それはかなり一口です)。次のキャラクターに移りましょう。

42.foo
 ^

まだ番号の一部であり、完全に有効なDecimalDigit.

42.foo
  ^

よし、これで本題から外れるDecimalIntegerLiteral。スキームの同じ図を次に示します。

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
                      ^

これは、数値の完全に有効な部分です。これをnumber の一部として消費し、先に進みます。

42.foo
   ^

fDecimalDigitsは の一部でも の一部でもありませんExponentPart。現在、数が不足しています。ならどうしよう?それは何fですか?それは何の一部でもありません。多分それはプロパティアクセサーですか?スキームを見てみましょう:

MemberExpression . IdentifierName
      ^

間違いなく ですMemberExpressionが、それに続くドットはありません。そのドットはすでに数字の一部です。構文エラーに達しました: 実行を停止してスローします。ガラスの家に住んでいないことを願っています。

うまくいけば、なぜ42..foo機能するのか理解できます。を抜けると、MemberExpression別の点に直面します。

              42..foo
                 ^
MemberExpression . IdentifierName
                 ^

完全に合法的な が続きIdentifierNameます。

もちろん、数字からドットを分離する方法は他にもいくつかあります。あなたが示したように、1つの方法は、リテラルを括弧で囲むことです: (42).foo. かっこの終わりに到達すると、 , から抜け出し、MemberExpression点に着きます。もう 1 つの方法は、スペースを挿入することです: 42 .foo、スペースは数値の一部にすることはできず、パーサーにとってニュートラルであるため、エラーは発生しません。

于 2013-09-01T08:13:27.380 に答える
35

たとえば、Ruby とは異なり、Javascript パーサーは.次の数字を数値の一部と見なします。したがって、パーサーはトークンを認識します。

23. toFixed ( 2 )

これは構文エラーtoFixedです。浮動小数点数の直後の単語が意味をなさないためです。この構文を受け入れる Ruby などの言語では、次のトークンが表示されます。

23 . toFixed ( 2 )

于 2013-09-01T06:29:44.050 に答える
23

検討:

5.

それは浮動小数点リテラルですか、5.それとも整数の5後にドットが続きますか? あなたは知りません。あいまいです。JavaScript は前者の見方をしています。JavaScript の観点では、浮動小数点リテラルの後に識別子が続きます (その後に左括弧、数値、右括弧が続きます)。

一部の人々は、2 つのドットを使用してこれを回避します。

23..toFixed(2)

浮動小数点リテラルは小数点を 1 つしか持てないため、もう 1 つのドットはリテラル ドット トークンです。

于 2013-09-01T06:30:38.147 に答える