We stumbled upon this today:
123.toString();
// Uncaught SyntaxError: Invalid or unexpected token
123 .toString();
// "123"
Why does adding the space work? Is the number literal being coerced or cast?
I've tried some other tests to shed some light, but I can't quite understand what's going on behind-the-scenes:
let number = 123;
number.toString();
// "123"
Object.prototype.toString.call(123);
// "[object Number]"
Object.prototype.toString.call(123 );
// "[object Number]"
In the first syntax, the .
is interpreted as a decimal separator (which must be adjacent to the digits). In that case toString
is unexpected, and represents a syntax error.
The property-dot does not have to be adjacent to the object it follows. Spacing is always allowed. So when you have the space, there is no ambiguity anymore, and the dot can be correctly interpreted.
Another variant is to double the dot:
123..toString()
Here the first dot is the decimal separator, but without digits following it (that is a valid syntax for a number). The second dot is then again the property-dot.
Or also:
(123).toString()
123.0.toString()
As long as you can make sure that the dot of .toString()
cannot be interpreted as a part of the number literal, it will work as you intended.
And when you access a property of a primitive, the primitive is boxed into a wrapper object on-the-fly, so that you actually do this:
Number(123).toString()
It's not about type conversion, coercion nor anything like that. You get SyntaxError because dot after the number is understood, syntactically, as a float number. toString
is not a valid part of float number syntax. Adding space allows parses to understand that you provided number and you want to call a method on the object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With