Detailed explanation
JavaScript has two equality operators: ==, called loose or abstract equality, and ===, called strict equality. Both return a boolean, but they handle operands of different types differently. Strict equality does not convert types: if the types differ, the result is false. Loose equality follows a defined set of conversion rules when types differ. This distinction matters because values from HTML inputs, URLs, and external data may not have the types your code expects.
For example, 0 == '0' is true because loose equality converts the string '0' to the number 0. However, 0 === '0' is false because one operand is a number and the other is a string. Similarly, false == 0 is true because the boolean becomes 0. Loose equality does not simply convert both operands to strings or check whether both are truthy. Its rules depend on the operand types; an object compared with a primitive may first be converted to a primitive through methods such as valueOf() or toString().
Strict equality is more predictable, but saying it compares “type and value” needs some qualification. For objects, including arrays and functions, equality checks identity rather than matching their contents. Two separately created objects are unequal under both operators, while two variables referring to the same object are equal. Also, NaN === NaN is false, and +0 === -0 is true. These are defined numeric equality behaviours, not examples of type conversion. When both operands already have the same type, == generally behaves like ===.
In everyday application code, prefer === and !==, and convert inputs explicitly when necessary. For example, Number(input) === 0 makes the intended conversion visible, although empty strings and whitespace also convert to zero. A useful deliberate exception is x == null, which checks for either null or undefined for ordinary values; it does not match 0, false, or an empty string. Interviewers usually look for correct examples, an understanding of coercion rather than memorised outputs, and awareness that neither operator performs deep object comparison.
Key points to remember
- === performs strict equality without type conversion; different types compare unequal.
- == applies type-dependent coercion rules, so 0 == '0' is true.
- For ordinary values, x == null matches null and undefined, but not other falsy values.
- Both operators compare objects by identity, not by their contents.
- Prefer === and !==; make necessary conversions explicit and validate the result.
Common mistakes candidates make
- Claiming == always converts both operands to numbers or compares their truthiness.
- Expecting separately created objects or arrays with identical contents to be equal.
- Assuming strict equality means NaN equals itself or that it distinguishes +0 from -0.
Likely follow-up questions
Why is [] == false true, but [] === false false?
Loose equality converts false to 0 and the empty array to the primitive empty string, which then converts to 0. Strict equality returns false immediately because the types differ.
How is Object.is() different from ===?
Object.is(NaN, NaN) returns true, whereas NaN === NaN is false. Object.is(+0, -0) returns false, whereas +0 === -0 is true; neither performs type coercion or deep object comparison.
Can I write the null check using only strict equality?
Yes: x === null || x === undefined explicitly checks both possibilities. For ordinary values, it has the same effect as x == null; a legacy browser exception is document.all, which loosely equals null.
Interview tip: Start with the coercion difference, walk through 0 versus '0', and finish with the strict-equality recommendation and the intentional null check.
