Reputation: 151036
I only found that the time .toString()
is called is with string concatenation and string interpolation:
// Inside of Node:
> let arr = [1,3,5];
> arr.toString()
'1,3,5'
> "" + arr
'1,3,5'
> arr + ""
'1,3,5'
> `${arr}`
'1,3,5'
Supposedly, console.log
prints out the string representation of the object and is supposed to use toString()
, but I am not sure whether it is toString()
not properly implemented usually, so console.log
does something else:
> console.log(arr);
[ 1, 3, 5 ]
> console.log("arr is %s", arr);
arr is [ 1, 3, 5 ]
So inside the JavaScript itself, when is toString()
ever called?
I think by polymorphism, anything we write ourselves, we can use ourObj.toString()
to get the string representation of our object as string. But I wonder within JavaScript itself (all its function, libraries, classes), when is toString()
actually invoked?
Upvotes: 1
Views: 158
Reputation: 151036
To illustrate some perhaps more common cases:
Array
's join()
Inside of Node console:
> let foo = { a: 123, toString: function() { return `an object with value ${this.a}`; } };
> foo
{ a: 123, toString: [Function: toString] }
> foo.toString()
'an object with value 123'
> foo.a = 456;
456
> foo.toString()
'an object with value 456'
> `${foo}`
'an object with value 456'
> "foo: " + foo
'foo: an object with value 456'
> "foo: ".concat(foo)
'foo: an object with value 456'
> let d = {};
> d[foo] = "hello";
'hello'
> d
{ 'an object with value 456': 'hello' }
> Symbol(foo)
Symbol(an object with value 456)
> String(foo)
'an object with value 456'
> let bar = Object.assign({}, foo); // clone
> bar.a = 789;
789
> [foo, bar].join(" - ")
'an object with value 456 - an object with value 789'
Upvotes: 0
Reputation: 350310
In several sections of the EcmaScript language specification, there is mention of toString
. One important use occurs in the abstract operation OrdinaryToPrimitive: this function will look for the object's toString
or valueOf
method, and execute it. The precedence can be influenced by a hint argument.
In turn, OrdinaryToPrimitive
is called by the abstract operation ToPrimitive
ToPrimitive
is called by ToNumber
, ToString
, ToPropertyKey
, relational comparison, equality comparison, evaluation of expressions, the Date
constructor, several stringification methods, like toJSON
, ...etc.
In fact, the language is soaked with internal operations that will get to executing ToPrimitive
. The specification has 200+ references to ToString
.
Here is a object with a toString
method implementation in order to prove that toString
is called internally.
Then follow a few expressions that each trigger toString
.
// Preparation
let obj = {
toString() {
this.i = (this.i||0) + 1; // counter
console.log("call #" + this.i);
return "0";
}
};
// Trigger toString via several constructs
({})[obj];
1 < obj;
1 == obj;
1 + obj;
1 - obj;
+obj;
Math.abs(obj);
parseInt(obj);
new Date(obj);
new RegExp(obj);
new Number(obj);
Symbol(obj);
"".localeCompare(obj);
[obj, null].sort();
[obj].join();
`${obj}`;
setTimeout(obj); // Not standard EcmaScript environment, but defined in the agent.
Some of these would not trigger toString()
if there were a valueOf
method defined on obj
which would return a primitive value.
Upvotes: 3