1

I have this code. And I don't understand how it works.

let obj = {
    valueOf: function () {
        return {};
    },
    toString: function () {
        return 222;
    }
};

console.log(Number(obj)); //222

According to this source, the conversion algorithm is:

  1. Call obj[Symbol.toPrimitive](hint) if the method exists,
  2. Otherwise if hint is "string" try obj.toString() and obj.valueOf(), whatever exists.
  3. Otherwise if hint is "number" or "default" try obj.valueOf() and obj.toString(), whatever exists.

Hint is number here. Then why is obj.toString() called? Is there no obj.valueOf()? Why? What kind of objects have this method? I can't find any useful information about this.

And here's another example:

var room = {
  number: 777,

  valueOf: function() { return this.number; },
  toString: function() { return 255; }
};

console.log( +room );  // 777

Why is obj.valueOf() called in this case? Why does this method exist here, and doesn't in the first example? How does it work?

Ivan
  • 478
  • 2
  • 13

1 Answers1

2

From the article you quoted:

Return types


The only mandatory thing: these methods must return a primitive, not an object.

Historical notes
For historical reasons, if toString or valueOf returns an object, there’s no error, but such value is ignored (like if the method didn’t exist).

In your first snippet, both methods exists and are tried: first obj.valueOf(), but since it returns an empty object not a primitive value, obj.toString() is also called.

In your second snippet, obj.valueOf() already return the number 777, which becomes the result.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • *"`obj.valueOf()`, whatever exists"*, *"`obj.toString()`, whatever exists"*... Actually, in what kind of situations these methods can't exist? Just out of curiosity – Ivan Jun 11 '21 at 21:18
  • @Ivan `Object.create(null)`, `{valueOf: null, toString: undefined}` – Bergi Jun 11 '21 at 21:48
  • I got it. I just need to nullify these methods. But I still have one more question. When does `obj[Symbol.toPrimitive]` exist? I see that there's mostly no `obj[Symbol.toPrimitive]` in simple objects. So, in what cases this method can be? – Ivan Jun 12 '21 at 11:47
  • @Ivan `Date` and `Symbol` instances have that method, also you can define it on your own objects and custom classes. – Bergi Jun 12 '21 at 12:14