5

Why does an empty array plus false return the string "false"?

> [] + false

> "false"

An empty array is false, right?

Then false + false = false? No?

Boann
  • 44,932
  • 13
  • 106
  • 138
OPV
  • 1
  • 16
  • 57
  • 124
  • 7
    empty array -> toString() -> `''` -> plus something -> string as result. – Nina Scholz Oct 19 '19 at 17:39
  • @NinaScholz This does not explain why there's a `.toString()` call in the first place. – Andreas Oct 19 '19 at 17:40
  • Operator `+` casts to `string` or `number` (whatever is possible, in this order). It doesn't cast to `Boolean`. – goodvibration Oct 19 '19 at 17:41
  • right, it is the plus sign, which triggers the operands to a usable form. – Nina Scholz Oct 19 '19 at 17:42
  • 2
    Would this work as a suitable dupe target? [What exactly is Type Coercion in Javascript?](https://stackoverflow.com/questions/19915688/what-exactly-is-type-coercion-in-javascript) – Andreas Oct 19 '19 at 17:43
  • To add: `+` does an **addition** on operands when they are a combination of numbers or Boolean (true=1, false=0, null=0) (`undefined` or `NaN` will result in `NaN`). Everything else would be **concatenation** by converting it to `string`. Also `[]` empty array is not `false`. – ambianBeing Oct 19 '19 at 18:39
  • Where you see array to string? – OPV Oct 19 '19 at 19:11
  • Do you mean this `if (typeof [] === "") { alert('equal'); }`? – OPV Oct 19 '19 at 19:15

4 Answers4

5

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]"
dee-see
  • 21,841
  • 5
  • 54
  • 87
2

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
goodvibration
  • 5,302
  • 1
  • 17
  • 43
2

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:

  1. If the operand is a primitive then stop.
  2. Otherwise call its .valueOf() method. If the return value is a primitive then stop.
  3. Otherwise call its .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".


What does 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.


How to make [] + false returns 42?

Simple:

  1. Force [] to return 42
  2. 42 + false will cause false to be coerced into a number: 0
  3. 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);
customcommander
  • 11,496
  • 3
  • 35
  • 53
1

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"

More info: Why is [1,2] + [3,4] = "1,23,4" in JavaScript?

Beniamin H
  • 1,882
  • 1
  • 8
  • 16