Why does an empty array plus false return the string "false"?
> [] + false
> "false"
An empty array is false, right?
Then false + false = false? No?
Why does an empty array plus false return the string "false"?
> [] + false
> "false"
An empty array is false, right?
Then false + false = false? No?
Short answer: because the spec says so.
Longer answer: When the left operand of the +
operator is not a string or a number, the operand will be converted to either one of those depending on their "preferred" primitive type (defined in the spec). The array's "preferred" type is a string and [].toString()
is an empty string.
Then, still according to the spec, because the left operand is a string (following the previous conversion), the right operand will be converted to a string and the result of the +
operation will be the concatenation of both strings.
In other words, [] + false
is equivalent to [].toString() + false.toString()
(or "" + "false"
) and results in the string "false"
.
Other interesting results as a consequence of this:
[1,2,3] + false // "1,2,3false"
[1,[2]] + false // "1,2false"
[] + {} // "[object Object]"
The '+' operator casts to string
or number
(whatever is possible).
It doesn't cast to Boolean
, check it out for yourself:
const x = [] + false;
const y = false + false;
console.log(typeof(x)); // string
console.log(typeof(y)); // number
The general rule for addition in JavaScript is simple: You can only add numbers and strings, all other values will be converted to either one of those types.
Source: https://2ality.com/2012/11/coercing-objects.html
First the +
operator must make sure that it operates on primitives (either numbers or strings). If an operand isn't a primitive it must first convert it.
Here are the rules:
.valueOf()
method. If the return value is a primitive then stop..toString()
method.In [] + false
, []
isn't a primitive. Let's convert it:
([]).valueOf(); //=> [] (not a primitive)
([]).toString(); //=> "" (primitive)
We now have "" + false
to solve.
If any operand is a string, then +
returns the concatenation of both operands. Meaning that false
must be converted to a string:
(false).toString(); //=> "false"
The final operation becomes "" + "false"
which returns "false"
.
false + false
return?Both operands are primitives and both aren't strings. So they must both be converted to numbers.
Number(false); //=> 0
+false; //=> 0
Therefore false + false
becomes 0 + 0
which returns 0
.
[] + false
returns 42
?Simple:
[]
to return 42
42 + false
will cause false
to be coerced into a number: 0
42 + 0
returns 42
Example:
var empty_arr = [];
empty_arr.valueOf = () => 42;
console.log(empty_arr + false);
Or: (but that's nasty)
Array.prototype.valueOf = () => 42;
console.log([] + false);
Basically it's because JS is trying to concat an array and then adds the string. Take a look on this:
[1] + true // "1true"
[2] + 5 // "25"
[2, 3, 4] + 5 // "2,3,45"
Similar to:
"".concat([3, 2, 1]); // "3,2,1"