Search code examples
javascriptobjecttostringvalue-of

When the method valueOf may be absent?


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?


Solution

  • 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.