I know that when JS tries to represent an object as primitive, it calls valueOf
method on an object. But today I found out that it also calls toString()
method in the same situation:
var o = {};
o.toString = function() {return 1};
1+ o; // 2
Why? If I add valueOf
method then toString
is not called.
The toString method is automatically called when something is printed using println. It also gets called when an object is concatenated with a String and can be called explicitly when required.
toString() gets invoked automatically. Object. toString() 's default implementation simply prints the object's class name followed by the object's hash code which isn't very helpful. So, one should usually override toString() to provide a more meaningful String representation of an object's runtime state.
toString . For user-defined Function objects, the toString method returns a string containing the source text segment which was used to define the function. JavaScript calls the toString method automatically when a Function is to be represented as a text value, e.g. when a function is concatenated with a string.
The toString() method is used internally by JavaScript when an object needs to be displayed as a text (like in HTML), or when an object needs to be used as a string. Normally, you will not use it in your own code.
I suppose the explanation lies in 8.6.2.6 chapter of ECMA-262 specification:
8.6.2.6 [DefaultValue]
[...]
When the [[DefaultValue]] method of O is called with hint Number, the following steps are taken:
Call the [[Get]] method of object O with argument "valueOf".
If Result(1) is not an object, go to step 5.
If Result(3) is a primitive value, return Result(3).
Call the [[Get]] method of object O with argument "toString".
If Result(5) is not an object, go to step 9.
Since your object doesn't implement valueOf, toString is used.
it all depends on the Hint.
when you use 1 + o
it is a number Hint because of the +
operand so it would definitely use valueOf
before toString
.
If the hint is String, then toString
is used before valueOf
. for example try ["o",o].join("=")
All together would be:
var o = {};
o.toString = function() {return 1};
o.valueOf= function(){return 2};
1 + o; // 1+2=3 ==> it takes valueOf value
["o",o].join("") //o1 ==> it takes toString value
TL;DR
When ToPrimitive is called with no hint
it acts as if the hint was number
. That defines methods to be called: first valueOf
then toString
. If you haven't defined your own valueOf
it will call Object.prototype.valueOf
that returns this.
BTW in modern browsers you can be more specific about it
const a = {
[Symbol.toPrimitive]: function(hint) {
console.log(hint);
return {
'default': 1,
'number': 2,
'string': 'three'
}[hint]
}
}
console.log(a + 1); //default, 2
console.log(+a + 1); //number, 3
console.log(`${a} + one`); //string, three + one
Long read:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With