3

I started reading YDKJS for fun - and found that he's written:

we can do stuff like:

var num = (1.2).toFixed(1)

so - this means that toFixed is being invoked as a member method from an integer value.

So why doesn't this work??

"toFixed" in 1.222

But this works:

"toFixed" in new Number(1.222)
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
Probosckie
  • 1,585
  • 4
  • 25
  • 40
  • 7
    `1.222` is a *primitive* - it doesn't have any methods. When you call `(1.2).toFixed(1)` that's being cast into a Number object. – VLAZ Aug 20 '19 at 14:55
  • so this is explicit coercion ?? – Probosckie Aug 20 '19 at 14:56
  • yeah, rather quite implicit :) – Jonas Wilms Aug 20 '19 at 14:56
  • Implicit, although it's a bit dubious whether it's coercion. `(1.2).toFixed(1)` is *almost* like `new Number(1.2).toFixed()` but you might not actually get an actual object, the environment might act *as if* you did that but not create, discard, and garbage collect an object. – VLAZ Aug 20 '19 at 14:57
  • @vlaz the optimization steps the engine takes are unrelated to the spec. They will behave *exactly* like that, the engine might optimize the constructor away in *both cases* (or it might not, who knows ...) – Jonas Wilms Aug 20 '19 at 15:07
  • In case any one wants to look up that implicit coercion in the spec, it is in `7.1.13 ToObject` wich gets called by GetValue. – Jonas Wilms Aug 20 '19 at 15:12
  • Possible duplicate of [What does the 'in' keyword in javascript mean?](https://stackoverflow.com/questions/16831812/what-does-the-in-keyword-in-javascript-mean) – weegee Aug 20 '19 at 15:15

1 Answers1

2

Page 268 of the Es262 spec states:

RelationalExpression : RelationalExpression in ShiftExpression

[...]

  1. Let rref be the result of evaluating ShiftExpression.

  2. Let rval be ? GetValue(rref).

  3. If Type(rval) is not Object, throw a TypeError exception.

So in other words: You can't use in on numbers. Thats just the way it is defined.

new Number however does not create a number, but a number object (an object that inherits from the Number.prototype). That's why you can use in on it, cause its an actual object.


You can still do 12..toFixed(), thats because of a very interesting construct in the spec: The abstract GetValue operation, which will be called when you access a property¹, does call toObject if the target (12 in this case) is not an object, and that will then do the following:

Return a new Number object whose [[NumberData]] internal slot is set to argument.

So in other words: 12..toFixed() is exactly the same as new Number(12).toFixed().

¹ interestingly accessing the property itself does not actually do that according to the spec, if you do a.b that will only look up the value of a and create a reference (Reference(a, "b")). The actual property lookup happens when GetValue gets called on it (however I don't know of any case were a Reference gets lost without calling GetValue on it).

Community
  • 1
  • 1
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • _You can still do `12..toFixed()`_ Which is nice but the OP asked about floats. Like `1.3` or `1.2`. Then how can we do this? – weegee Aug 20 '19 at 15:23
  • 1
    @weegee there is no such thing as "floats" in js. "floats" are just numbers. – Jonas Wilms Aug 20 '19 at 15:26
  • I know but I used the word to represent decimal values. – weegee Aug 20 '19 at 15:27
  • @weegee I don't get your point. There is no technical difference between `12..toFixed()` and `1.2.toFixed()`. – Jonas Wilms Aug 20 '19 at 15:28
  • 1
    @weegee *all* numeric primitives in JS are represented as a IEEE 754 floating point number. Both `-2` and `0.5` have a sign, mantissa, and exponent represented in binary as per the same standard. There is no difference between the two numbers safe for what the values of those three components - any operation done on *any* primitive number will be resolved using the same mechanisms as with any other number. – VLAZ Aug 20 '19 at 16:13