Suggest an editImprove this articleRefine the answer for “Why [] == false returns true”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Because loose comparison with `==` coerces both sides to a number, and the engine ends up comparing `0 == 0`.** First `false` becomes the number `0`, then the array, being an object, is coerced to a primitive through `valueOf()` and `toString()`, which for an empty array yields the empty string `''`, and `Number('')` is `0` again. Strict comparison does none of this: `[] === false` is always `false`, because the types differ and no coercion happens. ```javascript [] == false; // true: false -> 0, [] -> '' -> 0, so 0 == 0 [] === false; // false: comparison without type coercion ``` **Key point:** `==` compares values after coercion, `===` compares type and value, which is why production code should use `===`.Shown above the full answer for quick recall.Answer (EN)Image**`[] == false` returns `true` because loose comparison makes JavaScript coerce both sides to a number, and it ends up comparing `0 == 0`.** Along the way the array becomes an empty string and the empty string becomes zero, so the equality turns out to be true even though nothing meaningful is equal here. ## Theory ### TL;DR - `==` triggers type coercion, `===` does not. - A boolean operand in a `==` comparison is always turned into a number first: `false` is `0`. - An object (and an array is an object) is coerced to a primitive through `valueOf()`, then `toString()`. - `[].toString()` gives the empty string `''`, and `Number('')` gives `0`. - So the expression reduces to `0 == 0`, which is `true`. - `[] === false` is `false`, because strict comparison performs no coercion. ### Quick example ```javascript console.log([] == false); // true console.log([] === false); // false // The same chain, written out by hand: console.log(Number(false)); // 0 console.log([].toString()); // '' console.log(Number('')); // 0 console.log(0 == 0); // true ``` ### Step by step explanation Take the expression: ```javascript [] == false ``` **Step 1. `==` triggers type coercion.** In a loose comparison JS tries to coerce the types so that the comparison becomes possible. The abstract equality algorithm in the ECMAScript specification states the rule as: > If one of the operands is of type `boolean`, it is converted to a number. **Step 2. Convert `false` to a number.** ```javascript false -> 0 ``` Now the expression looks like this: ```javascript [] == 0 ``` **Step 3. An object (an array) on the left, a primitive on the right.** If one of the operands is an object, it is first coerced to a **primitive** (through `valueOf()`, then `toString()`). For the array `[]`: ```javascript [].toString(); // '' ``` So: ```javascript [] -> '' // empty string ``` And now we have: ```javascript '' == 0 ``` **Step 4. Comparing `'' == 0`.** By the same algorithm: > If one operand is a string and the other is a number, the string is converted to a number. ```javascript Number('') -> 0 ``` So: ```javascript 0 == 0 ``` The result: ```javascript true ``` ### Summary of the steps | Stage | Expression | What happened | | --- | --- | --- | | 1 | `[] == false` | `false -> 0` | | 2 | `[] == 0` | `[] -> ''` | | 3 | `'' == 0` | `'' -> 0` | | 4 | `0 == 0` | `true` | ### Why this is dangerous This logic makes `==` **unpredictable**. Here are more examples of the same mechanism: ```javascript [] == ![] // true '' == 0 // true '0' == 0 // true null == undefined // true [] == '' // true [0] == 0 // true [1] == 1 // true [2] == 2 // true ``` The first line is the most telling one: `![]` is `false` (an array is always truthy, so negating it gives `false`), then the familiar chain runs and `[] == ![]` also becomes `true`. A value equals its own negation, and that is perfectly legal JavaScript. ### How to avoid the confusion Use **strict comparison `===`**, which **performs no implicit type conversion**. ```javascript [] === false // false '' === 0 // false null === undefined // false ``` A short recap: | Expression | What JS does | Result | | --- | --- | --- | | `[] == false` | `[] -> '' -> 0`, `false -> 0` | `true` | | `[] === false` | Compares without coercion | `false` | If you need to check whether an array is empty, check it explicitly: ```javascript if (items.length === 0) { // empty array } ``` ### Common mistakes - **Checking an array for emptiness by comparing it with `false` or `0`.** It works by accident and breaks as soon as the value becomes `null` or an object. Check `items.length === 0` instead. - **Reading `[] == false` as "an array is falsy".** An empty array is in fact truthy: the body of `if ([])` runs. The falsiness here appears only because `==` coerces it to a number. - **Mixing up `==` and `===` in null checks.** Here `==` is occasionally useful: `x == null` catches both `null` and `undefined`. But that is the one exception, and it should be used deliberately. - **Relying on `valueOf()` for arrays.** For a plain array `valueOf()` returns the array itself, which is not a primitive, so the engine falls through to `toString()`. Override `valueOf()` and the comparison result changes. - **Ignoring the linter.** The ESLint `eqeqeq` rule bans `==` precisely because of cases like this, and turning it off for "shorter code" is not worth it.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.