2013-09-01 13 views
47

リテラル関数を呼び出そうとしていますが、私は奇妙な動作をします。数値リテラルのメンバー関数を呼び出す

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

23 === (23) 

私は次のように書きます。

(23).toFixed(2) 

私が期待した結果_23.00_を得るが、私は23.toFixed(2)をしようとすると、私はこのエラーを取得します。

SyntaxError: Unexpected token ILLEGAL

JavaScriptでこれを理解できない表現がどのように評価されますか。なぜこのエラーが発生しますか?

答えて

58

Greg Hewgillicktoofayの回答はすべて正しいですが、私はちょっと抽象的な言い方をしておきたいと思います。実際にjavascriptの仕様に従って何が起こっているのか見てみましょう。

Section 7.8.3は、数値リテラルを定義します。我々は次のことを見ることができます:

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

DecimalIntegerLiteral :: 
    0 
    NonZeroDigit DecimalDigits(opt) 

DecimalLiteral、数は、おそらく可能性指数が続くことができる他の数字(全てが続いている点、続いて、桁の束であり、例えばe12)。換言すれば、42.は合法であり、42に等しく、3e2300に等しい。

ドットがある場合は、数字/指数のほうが後ろに来るか、何も続きないことに注意してください。しかし、これは重要な部分です。ドットは番号の一部です。これを覚えておくと、ドット演算子obj.propがどのように処理されているかを見ていきます。

Section 11.2.1, Property Accessorsは、メンバーアクセスのためのドットとブラケット表記法について説明します。

MemberExpression . IdentifierName 

CallExpressionは、我々は気にしない関数呼び出し、ためです。 MemberExpression(これはDecimalLiteralでもかまいませんが、私の言葉を取って、見て、私が正しいかどうかはわかりません)を期待しています。

小さなドットを参照してください。 「ここにスキームにドットがあります。4.fooにドットがあります...なぜ、エラーがあるのですか?」私がこれらの文章のために使っている私の仮説的な友人のように、DecimalLiteralの様子を忘れてしまった! 2つの例を見て、何が起こるか見てみましょう。

42.foo 
^ 

キャレットは、現在のキャラクターを表します。これまでのところ、私たちはDecimalLiteral/DecimalIntegerLiteral/NonZeroDigitの中にいます(それはかなり口が開いています)。それでも

42.foo 
^ 

数、完全に有効なDecimalDigitの一部:のは、次の文字に移動しましょう。

42.foo 
^

okですので、私たちはDecimalIntegerLiteral部分を使い果たしています。スキームに関する同じダイアグラムは次のとおりです。

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt) 
        ^

これは数字の完全な有効部分です。今、私たちは数の一環として、それを消費し、上の移動:

42.foo 
^

fDecimalDigitsのもExponentPartのどちらも一部であり、我々は今、数の出ています。ならどうしよう?それは何ですか。f?それは何の一部でもありません。たぶんそれはプロパティのアクセサーですか?スキームを見てみましょう:

MemberExpression . IdentifierName 
    ^

我々はMemberExpressionに間違いだが、我々はそれを次の点がありません - ドットは、すでに数の一部であることを。文法上のエラーに達しました。実行を停止してスローします。うまくいけば、あなたはガラスの家に住んでいないことを望みます。

うまくいけば、なぜ42..fooが機能するのかを理解してください。

   42..foo 
       ^
MemberExpression . IdentifierName 
       ^

完全に合法IdentifierName続く:私たちはMemberExpressionの出ているならば、我々は別のドットに直面しています。

もちろん、ドットと数字を区別する方法はいくつかあります。あなたが示したように、1つの方法は、リテラルを括弧で囲むことです:(42).foo。カッコが終わったら、MemberExpressionとドットの外に出ています。もう1つの方法は、空白を数値の一部にすることはできず、パーサーにとっては中立であるため、エラーを発生させないために、スペースを挿入することです(42 .foo)。

+1

優秀な回答! –

35

Rubyとは異なり、Javascriptパーサは、数字の後に数字の後に.があるとみなします。

23.toFixed(2)

単語がすぐに浮動小数点数は意味をなさない以下toFixedので、構文エラーです:だからパーサはトークンを見ています。

23.toFixed(2)

24

考えてみましょう::受け入れ、この構文は次のトークンが見るだろうなRubyなどの言語

5. 

は、浮動小数点5.リテラルまたは整数です5ドットが続く?あなたは知らない。あいまいです。 JavaScriptは元のビューを取ります。 JavaScriptのビューでは、浮動小数点型のリテラルとそれに続く識別子(その後に左括弧、数字、右括弧が続きます)があります。

一部の人々は2つのドットを使用することによってこの問題を回避:浮動小数点以来

23..toFixed(2) 

はリテラルだけおそらく1つの小数点を持つことができ、他のドットがリテラルのドットトークンです。

+1

23.0.toFixed(2) 'も動作します – Ehtesham

関連する問題