Hyphen Wrex
Hyphen Wrex

Reputation: 685

Why JavaScript behaves like that?

Let's look at those examples:

var a = 1;
var b = { toString:function() {return '1'} };
var c = 1;

a + b + c === "111" // true

It is pretty mind blowing. I know that JS interpreter performs ToPrimitive or ToString operations when we use + operator. But why is object b gets converted to a string when there is no hint PreferredType. Thus it is probably using ToString operation.

Another note: it is only gets converted to string if there is toString method exists on object, why? And if I call that method "toNumber", why it is not converted to number?

Why JavaScript behaves like that?

Upvotes: 0

Views: 115

Answers (1)

Felix Kling
Felix Kling

Reputation: 816472

But why is object b gets converted to a string when there is no hint PreferredType.

When no hint is passed, then the object's valueOf method will be called first. But since b.valueOf() doesn't return a primitive value (it returns the object itself by default), b.toString() will be called next.

See the specification.

The conversion rule can be summarized as follows:

  • If there is no hint or hint is number, call valueOf first.
  • If hint is string, call toString first.
  • If the return value is not is not a primitive value, call the other method.
  • If the return value is still not a primitve, throw an error.

it is only gets converted to string if there is toString method exists on object, why?

Not sure I understand this statement. Every object has a toString method. If you try to perform this operation on an object without a toString method (via Object.create(null)), an error is thrown.

And if I call that method "toNumber", why it is not converted to number?

Because toNumber has no meaning in JavaScript. toString and valueOf are the two "magic" methods via which objects are converted to primitive:

var n = 1;
var o = {
  toString() { return 'bar'; },
  valueOf() { return 2; }
};

console.log(n + o);
console.log(String(o));

If none of the methods return a primitive, you would get an error as well.

    var n = 1;
    var o = {
      toString() { return this; },
    };

    console.log(n + o);

These two methods and their naming seems kind of arbitrary. From ES6 on, the preferred way to define a conversion function is to use the well-known @@toPrimitive symbol:

var a = 1;
var b = { [Symbol.toPrimitive]: function() {return 1} };
var c = 1;

console.log(a + b + c);

@@toPrimitive is called before valueOf or toString are called.

Why JavaScript behaves like that?

Because that's how it is defined in the specification. If you want to know the rationale behind that, you have to ask the people who made that decision.

Upvotes: 7

Related Questions