This is a behavior that is due to the nature of coercion typical of Javascript. It is a language that historically relies on automatic type conversion, so there are several mechanisms for this to be done.
In the case of + (both binary and unary) and most other operators performing the conversion to the expected type, there are a number of steps to be taken so that the Runtime decided as convert to the appropriate value.
Below we explore how the conversion of objects to an expected primitive works. In the case of this answer, the expected result is number, but may vary depending on the operator used.
In the end, the steps are very similar. Just follow the algorithm described in spec.
Why + invokes the valueOf? What is the relationship between them?
Why is language design.
In the case of the anointing +, the specification (among the many listed steps) applies the abstract operation ToNumber that, in the case of objects (i.e., values in which the valueOf is taken into account), flame ToPrimitive, what call OrdinaryToPrimitive, which finally calls the method valueOf on objects.
In the case of torque +, that operates in "string mode" or "numeric mode", this may occur:
- In string mode, the abstract operation is called
ToString to operands. Following for objects, invoke ToPrimitive which, as we have seen above, will invoke OrdinaryToPrimitive.
- In numerical mode, it is called the abstract operation
ToNumeric, so that similar steps occur to what occurred at the anointing, only for the two arguments.
Note, in the algorithm of OrdinaryToPrimitive, that he first tries to summon valueOf and, if not available, has fallback at the toString. This already explains the behavior demonstrated in the question.
It is something very subtle and little used (many people don’t even know that the valueOf exists), so you don’t see much about it.
I wouldn’t expect anyone (except perhaps library creators) to use this mechanism to develop code on a daily basis. It’s something extremely obscure.
And of course, Javascript had to complicate it a bit more. In most type conversions, if there is a method defined by @@toPrimitive (that’s a well known Symbol) in the object to which the conversion is to be performed, it will be used. Basically, before the abstract operation is invoked OrdinaryToPrimitive, the implementation tries to call the method defined by this well known Symbol. In case he’s undefined, is used OrdinaryToPrimitive as fallback.
To understand, think about @@toPrimitive as a conversion operation nonordinary. In case it does not exist, conversion is used ordinary.
Only the operator + does it? Or the same is repeated for some other?
This behavior nay is unique to the +.
As Javascript is a language that makes several types of coercion typical. Therefore, most operators who make type coercion automatically are "susceptible" to the method valueOf. This is because the various conversions that Javascript makes culminate in the abstract operation OrdinaryToPrimitive which, as we have seen above, ends up invoking the valueOf.
By default, it’s called the valueOf. If this does not exist, it is invoked toString. In the case of coercion aiming at a conversion to the string type, the toString is called before the valueOf, if it exists. The @@toPrimitive is always prioritized, if there is.
On the last topic of the question, the result is different because, in the first case, the + was used as a binary operator that performs concatenation. In the second example, the + was used as an unary operator in order to carry out the conversion to type number.
bizarre things from
javascript, I can’t imaginenew User() + new User()in java, c, c++ or c# for example :D– Ricardo Pontual
@Ricardopunctual would be so simple if I made just one exception...
– Cmte Cardeal
because it is, javascript deceives us, not error in many situations, but returns something difficult to understand
– Ricardo Pontual