72

 

Why does calling 152..toString(2) return a binary string value of "10011000", when a call to 152.toString(2) throws the following exception?

          "SyntaxError: identifier starts immediately after numeric literal"


It seems to me that it's intuitive to want to use the latter call to toString(), as it looks & feels correct. The first example just seems plain odd to me.

Does anyone know why JavaScript was designed to behave like this?


JΛYDΞV
  • 8,532
  • 3
  • 51
  • 77
Andre Meinhold
  • 5,087
  • 3
  • 21
  • 29

3 Answers3

104

A . after a number might seem ambiguous. Is it a decimal or an object member operator?

However, the interpreter decides that it's a decimal, so you're missing the member operator.

It sees it as this:

(10.)toString();  // invalid syntax

When you include the second ., you have a decimal followed by the member operator.

(10.).toString();

@pedants and downvoters

The . character presents an ambiguity. It can be understood to be the member operator, or a decimal, depending on its placement. If there was no ambiguity, there would be no question to ask.

The specification's interpretation of the . character in that particular position is that it will be a decimal. This is defined by the numeric literal syntax of ECMAScript.

Just because the specification resolves the ambiguity for the JS interpreter, doesn't mean that the ambiguity of the . character doesn't exist at all.

I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • why the interpreter decides so ? Is there any spec about that? I makes still no sense to me, the interpreter should treat it like a property because its much more likely.... – Andre Meinhold Oct 30 '12 at 23:58
  • http://stackoverflow.com/a/6853910/1026459 – Travis J Oct 31 '12 at 00:00
  • 8
    The `.` is *not* ambiguous. See my answer. – Alnitak Oct 31 '12 at 00:02
  • @Alnitak: It presents an ambiguity because what would otherwise appear to be a valid placement of the same character could have two different behaviors. I'm not saying the specification is ambiguous. I'm saying the syntax is. The ambiguity is resolved in a specified manner. – I Hate Lazy Oct 31 '12 at 00:06
  • 3
    Lexers don't deal in ambiguity. *Parsers* do that. By the time these two expressions get to the parser the lexer has already made an unambiguous decision about which characters are grouped into which token. – Alnitak Oct 31 '12 at 00:07
  • @Alnitak: How does the lexer decide what is a valid numeric literal? – I Hate Lazy Oct 31 '12 at 00:11
  • by scanning characters until it finds a sequence which is no longer valid. A JS numberic literal cannot have more than one decimal point in it, so as soon as the second one is seen it emits a token with everything seen _up to_ (but not including) that point. – Alnitak Oct 31 '12 at 00:13
  • @Alnitak: Yes, but how does it decide what is and is not valid? It decides according to the numeric literal syntax specified in ECMAScript. So there's an ambiguity because the same token is used for two different purposes, but the ambiguity is resolved by the spec. – I Hate Lazy Oct 31 '12 at 00:15
  • the dot is a _character_, not a _token_. – Alnitak Oct 31 '12 at 00:16
  • @pst: I think you're trying to push my use of the word into a corner. From the perspective of the developer, it's ambiguous. If it wasn't, the developer wouldn't be having this issue. – I Hate Lazy Oct 31 '12 at 18:36
  • I would say "it is parsed as a decimal", but that is a larger change to the wording then I was willing to commit to. –  Oct 31 '12 at 18:42
  • @user1689607 re: your edit - every character is legal within a string literal. Does that make _them_ ambiguous too? – Alnitak Nov 02 '12 at 15:30
  • @Alnitak: Discussions have context, but in a broader sense yes. The behavior of the characters within a string literal could be interpreted to have different meanings. – I Hate Lazy Nov 02 '12 at 15:38
  • @Alnitak: Your answer states *"The lexer ... when it sees a digit will keep consuming characters ... until it sees a character that is not part of a legal number."* Are you saying that once a lexer sees a digit, it will only consume characters that are part of a legal number, and it will then halt? Are you saying that its behavior is identical when it finds a digit within a string or regex literal? I felt no need to call you out on this, because it would be mere pedantry to do so. – I Hate Lazy Nov 02 '12 at 15:42
  • @user1689607 yes, I omitted a step - the text I wrote applies when the lexer is reading a _new_ token. – Alnitak Nov 02 '12 at 15:43
101

The lexer (aka "tokenizer") when reading a new token, and upon first finding a digit, will keep consuming characters (i.e. digits or one dot) until it sees a character that is not part of a legal number.

<152.> is a legal token (the trailing 0 isn't required) but <152..> isn't, so your first example reduces to this series of tokens:

<152.> <.> <toString> <(> <2> <)>

which is the legal (and expected) sequence, whereas the second looks like

<152.> <toString> <(> <2> <)>

which is illegal - there's no period token separating the Number from the toString call.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 7
    This is the clearest and most accurate answer, it should be accepted over the user1689607 one. – cweekly Nov 02 '12 at 13:54
  • 3
    As a sidenote jsparse (http://jsparse.meteor.com/) has a realtime js lexer/parser, where you can see that the js engine parses "10." as a number. –  Nov 02 '12 at 14:13
  • @SzabolcsKurdi: That thing is *gorgeous*! – T.J. Crowder Jul 22 '14 at 15:30
0

10. is a float number an you can use toString on float

eg.

parseFloat("10").toString() // "10"
Anoop
  • 23,044
  • 10
  • 62
  • 76
  • 1
    Well 1 is a int and you can call int on a float too, the real problem is parser ambiguity, as user1689607 mentioned – Ruan Mendes Oct 30 '12 at 23:55
  • 3
    @JuanMendes: there is no such thing as `int` in javascript – georg Oct 30 '12 at 23:56
  • 1
    @thg435 There's not a type called `int`, but internally ints and floats are represented differently. My point is that the parser reads is as an integer, and `10.toString()` is ambiguous, it's impossible to tell if the . is for property access or the start of a float – Ruan Mendes Oct 30 '12 at 23:57
  • @JuanMendes the lexer and parser don't treat ints and floats separately. There's simply no such thing as an "integer literal" in JS. – Alnitak Oct 31 '12 at 00:21
  • @JuanMendes (unless it's in hex, that is) – Alnitak Nov 01 '12 at 09:02
  • Why not just use `(10).toString()` ? – Bentleyo Apr 21 '13 at 03:27