In some cases it does, but not in this case. The reason you see behaviour that may appear to be right-to-left evaluation is because of operator precedence, where the unary ! has a higher precedence than the binary +.
+ actually evaluates from left to right, so more verbosely parenthesized, it looks like this:
(((!(+[]))+[])+(![])).length
Evaluating this parenthesized form step-by-step, we get this:
/* 1. */(((!(+[]))+[])+(![])).length// parethesized form./* 2. */(((!0)+[])+(![])).length// `+[]` is evaluated to `0`./* 3. */(((!false)+[])+(![])).length// `0` is coerced to the boolean `false`./* 4. */((true+[])+(![])).length// `!false` is evaluated to `true`./* 5. */(("true"+"")+(![])).length// `[]` is coerced as a primitive to the string `""`, which means `true` is also coerced to a string./* 6. */("true"+(![])).length// `"true" + ""` is string concatenation, which evaluates to `"true"`./* 7. */("true"+(!true)).length// `[]` is coerced to the boolean `true`./* 8. */("true"+false).length// `!true` evaluates to `false`./* 9. */("true"+"false").length// `false` is coerced to a string because `"true"` is a string./* 10. */"truefalse".length// `"true" + "false"` is evaluated as string concatenation to `"truefalse"./* 11. */9// the length of `"truefalse"` is `9`.
In some cases it does, but not in this case. The reason you see behaviour that may appear to be right-to-left evaluation is because of operator precedence, where the unary
!
has a higher precedence than the binary+
.+
actually evaluates from left to right, so more verbosely parenthesized, it looks like this:Evaluating this parenthesized form step-by-step, we get this:
The first + is unary, right?
Indeed it is.