Reputation: 685
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
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:
number
, call valueOf
first.string
, call toString
first.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