console.log("12"+ {"x":"1",toString(){return 10;},valueOf(){return 90}});
In the above expression why toString() method is not called? As per the algorithm if either the left or right side there is string then we call ToString() with hint as "String" for another side and if hint is "String" then the toString() method will be called first and then the valueOf() method. But the above expression is given answer as "1290" mean valueOf() is called.
Algorithm for additive expression: –
12.8.3The Addition Operator ( + )
NOTE
The addition operator either performs string concatenation or numeric addition.
12.8.3.1Runtime Semantics: Evaluation
AdditiveExpression:AdditiveExpression+MultiplicativeExpression
Let lref be the result of evaluating AdditiveExpression.
Let lval be ? GetValue(lref).
Let rref be the result of evaluating MultiplicativeExpression.
Let rval be ? GetValue(rref).
Let lprim be ? ToPrimitive(lval).
Let rprim be ? ToPrimitive(rval).
If Type(lprim) is String or Type(rprim) is String, then
Let lstr be ? ToString(lprim).
Let rstr be ? ToString(rprim).
Return the string-concatenation of lstr and rstr.
Let lnum be ? ToNumber(lprim).
Let rnum be ? ToNumber(rprim).
Return the result of applying the addition operation to lnum and rnum. See the Note below 12.8.5.
ToString rules: –
7.1.12ToString ( argument )
The abstract operation ToString converts argument to a value of type String according to Table 11:
Table 11: ToString Conversions
ToString conversion table:
According to the ToString Conversion table if there is object then hint "String" will be used.
Please help me out in this problem why valueOf() method is preferred.
2
Answers
As I read the spec,
13.8.1 The Addition Operator ( + ) specifies this in terms of
ApplyStringOrNumericBinaryOperator
wherelval
is"12"
opText
is+
rval
is{"x":"1",toString(){return 10;},valueOf(){return 90}})
As I see it,
rprim := ToPrimitive(rval)
there ends up invokingOrdinaryToPrimitive(..., "number")
, which prefersvalueOf
totoString
.There’s a note at the bottom of the section 7.1.1 ToPrimitive (input [, PreferredType]) that states
Which is why you’re seeing the results of calling
valueOf()
instead oftoString()
. It also mentions that we can override this behaviour too so thattoString()
is called:This now behaves as you originally expected and calls
toString()
and outputs1210