This installment of wtfjs has to do with implicit type conversion during arithmetics and operator ambiguity / overloading.
If you can figure out what this returns on the first guess, I'll give you a great big hug the next time I see you:
// is there an error (if not, what do I return?) "3" -+-+-+ "1" + "1" / "3" * "6" + "2"
Firstly, I'm not sure about you guys, but I forgot some basic stuff from elementary school math - order of operations. One usually doesn't look at these when doing (supposed) string concatenation (but we're doing a little bit more than that, aren't we?).
delete void typeof ++ -- + - ~ ! * / % + - << >> >>> < > <= >= instanceof in == != === !== & ^ | && || ? : = *= /= %= += -= <<= >>= >>>= &= ^= |=
First you'll notice that the
+ occurs twice (already a bit confusing), but
additionally can be used for string concatenation based on contextual cues and
type hints (i.e.
5 + "2" = "52", not
11.6.1 The Addition operator ( + ) The addition operator either performs string concatenation or numeric addition.
If Type(lprim) is String or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim).
So this means we'll have to find out what which + is doing what.
Additionally, you can throw a unary
- operator onto
like candy to change their signs and make things prettier and easier to
understand for your fellow developers. Note that every
- flips the sign, but
+ does essentially nothing functionally to the result of the
+1 === 1).
+ can be useful to cast to numbers (hence the
+new Date hack we
often see to emulate
Date.now()) and to guarantee you're casting to decimal
11). This method has the
drawback, however, that it can't handle letters in the string (i.e.
1, and accidental octal conversion
number guessing by
parseInt can be fixed by adding a base to
parseInt("08", 10) is
These unary operators are evaluated first as they have the highest precedence,
so we start with the result of
+-+-+"1" (notice how the first
- is treated
as the operator when evaluating an
AdditiveExpression). The result of this is
NOTE: This ignores your grammar teacher's rules about double negatives.
Let's make this line into an expression tree. After unary operators are evaluated, we have:
+ "2" + * - / "6" 1 "3" "1" "3"
However, we don't know what types are implicitly cast yet. Let's make another
tree showing non-ambiguous operations (
+ "2" + * - / 6 1 3 1 3
This greatly simplifies the bottom of the tree as they're all now numbers. We continue evaluating from bottom left most child up, which evaluates the expression as so: (3-1)+((1/3)*2) = 2 + 2 = 4. This leaves us with this tree:
+ "2" 4
This last operation is ambiguous, so we look to see if either operand is a
"2" is), so the type of
rprim is), so the final result is
(which is the obvious answer to life the universe and everything, really).