In JavaScript, null == undefined is true, but null == 0 and null == false are both false. Which rule of the loose-equality algorithm explains this?
answer
- a rule of its own, early in the algorithm
- these two are never converted
- equal to each other, to nothing else
- Number(null) is zero, the comparison still is not
basics
~20 sThe loose-equality algorithm has an explicit step making null and undefined equal to each other and to nothing else. Neither value is ever converted to a number, so null == 0 and null == false both fall through to false.
solid answer
~50 sLoose equality contains a dedicated step for these two values: if one operand is `null` and the other is `undefined`, the result is `true` — and there is no rule anywhere that converts `null` or `undefined` to a number, a string, or a boolean. So `null == undefined` and `null == null` are true, while `null == 0`, `null == false`, `null == ''` and `undefined == 0` all fall through to the final "otherwise return false" step. This is the one piece of loose equality worth exploiting: `x == null` is a compact, exact test for "x is null or undefined", equivalent to `x === null || x === undefined` and matching nothing else. It is also why loose equality is not a general falsiness test — `null` is falsy, yet it is loosely equal to no other falsy value.
code
javascript · 7 linesconsole.log(null == undefined); // true
console.log(null == null); // true
console.log(null == 0); // false
console.log(null == false); // false
console.log(null == ''); // false
console.log(undefined == 0); // false
console.log(Number(null)); // 0 - explicit conversion disagreesgo deeper
Remember that null == undefined is true and that null == 0 is false, and that writing x == null is a normal way to check for a missing value.
Explain the mechanism: an explicit algorithm step pairs null with undefined, and no rule ever converts either one, so everything else falls through to false. Note that Number(null) being 0 is a separate conversion.
Show the judgment call about which absent value you mean — an exact nullish check that preserves 0 and '' versus a falsiness check that discards them — and name the data-loss bug the wrong choice causes.
Own the modelling question behind the trivia: decide whether a field may hold both absent values at all, and normalise absence to a single representation at the parsing boundary so downstream code never has to choose between the two checks.
## The rule, stated exactly The abstract equality comparison checks, right after the same-type shortcut, whether one operand is `null` and the other is `undefined`. If so the answer is `true`. Nothing later in the algorithm ever converts `null` or `undefined` into another type — there is no "ToNumber(null)" branch in the comparison. That is the whole explanation, and it produces a clean, memorable result: **`null` and `undefined` are loosely equal to each other and to nothing else in the language.** ```js console.log(null == undefined); // true - the special rule console.log(null == null); // true - same type, strict console.log(undefined == undefined); // true console.log(null == 0); // false console.log(null == false); // false console.log(null == ''); // false console.log(null == NaN); // false console.log(undefined == 0); // false ``` (One host-provided legacy object in browsers, `document.all`, is deliberately specified to compare loosely equal to `null` and `undefined` as a web-compatibility quirk. It is trivia, not a rule you can build on.) ## Why people expect otherwise The usual wrong prediction is `null == 0` being true, and it comes from mixing up two different conversions. `Number(null)` really is `0` — explicit numeric conversion of `null` produces zero, which is why `null + 1` is `1`. But the loose-equality algorithm never performs that conversion; it short-circuits on the null/undefined step and then runs out of applicable rules. So explicit conversion and implicit comparison genuinely disagree here, and the candidate who says "but `Number(null)` is 0" is right about the conversion and wrong about the comparison. The same trap appears with relational operators, which use a *different* algorithm that does convert: `null >= 0` is `true` and `null > 0` is `false`, while `null == 0` is `false`. So `null` is simultaneously "not equal to 0" and "greater than or equal to 0". This is a good illustration that `==` is its own algorithm rather than a general coercion policy applied everywhere. ## null is falsy, but that is a separate system `null` and `undefined` are both falsy, and so are `0`, `''`, `NaN` and `false`. It is tempting to conclude that falsy values are loosely equal to one another. They are not. Falsiness is decided by a boolean conversion used in `if` and `!`; loose equality is decided by the algorithm above. The two overlap in some cases (`'' == 0` is true) and diverge sharply in others (`null == 0` is false; `'0' == false` is true even though `'0'` is truthy). Treat them as unrelated mechanisms that happen to share some inputs. ## The one useful idiom Because the rule is exact, `x == null` is a precise test for "x is null or undefined" and nothing else: ```js function has(value) { return value != null; // false only for null and undefined } console.log(has(0)); // true - zero is a real value console.log(has('')); // true - empty string is a real value console.log(has(NaN)); // true console.log(has(null)); // false console.log(has(undefined)); // false ``` This is the check you want when a parameter is optional and `0`, `''` or `false` are legitimate values — a quantity, a search term, a toggle. Writing `if (!value)` there is the classic bug: it rejects `0` and `''` along with the genuinely-missing cases. ## Distinguishing the two absent values when you must `x == null` deliberately blurs `null` and `undefined`. Sometimes that distinction matters: `undefined` typically means "never set / property absent / argument omitted", while `null` usually means "explicitly set to nothing", and some data sources use them differently. When the difference is meaningful, test strictly — `x === undefined` or `x === null` — and be explicit in the code about which case you are handling. A default parameter value, for example, is applied only for `undefined`, never for `null`, so a function that receives `null` will not get its default. ## What to say in the interview State the rule first: there is an explicit step for null-versus-undefined, and neither value is ever coerced. Then give the two consequences — `null == 0` is false despite `Number(null)` being `0`, and `x == null` is an exact nullish check. If you have room, mention that relational comparison uses a different algorithm and does convert, so `null >= 0` is true. That trio shows you are reading the algorithm rather than reciting habits.
- Number(null) is 0, so why doesn't null == 0 follow from that?Because loose equality never calls ToNumber on `null`. The algorithm hits its null/undefined step, finds the other operand is a number rather than `undefined`, and falls through to the final `false`. Explicit conversion and the comparison algorithm are separate mechanisms — `null + 1` really is `1`, and `null == 0` really is `false`.
- When would you deliberately test x === undefined instead of x == null?When the distinction carries meaning — for example when `undefined` means "the property was never present" and `null` means "explicitly cleared", which some APIs and stored documents rely on. Default parameter values also apply only for `undefined`, so a function passed `null` skips its default. If both absent-ish cases should behave the same, `x == null` is the clearer check.
- Why is if (!value) a poor substitute for if (value == null)?`!value` is a falsiness test, so it also fires for `0`, `''`, `NaN`, `-0`, `0n` and `false`. If any of those is a legitimate value — a count of zero, a cleared search box, a switched-off toggle — the check misclassifies real data as missing. `value == null` matches exactly the two absent values and leaves everything else alone.
saying these in an interview costs you the question
- null == 0 is true because Number(null) is 0
- null is loosely equal to every falsy value
- null == undefined is false because their types differ
- undefined == '' is true since both are empty
- == null and !value are interchangeable checks