Comparison

JavaScript == vs ===: Loose vs Strict Equality Explained

Compare JavaScript's == and === operators: how coercion works, NaN and null quirks, Object.is differences, and when loose equality is actually useful.

JavaScript == vs ===: Loose vs Strict Equality

JavaScript ships two equality operators and they behave very differently. === (strict equality) compares without any type conversion: if the operands are different types, the result is always false. == (loose equality) runs the Abstract Equality Comparison algorithm from the ECMAScript spec, which coerces operands toward a common type before comparing.

How each operator works

Strict equality (===): same type required. Numbers compare by value, strings by contents, booleans by value, and objects by reference. No conversion happens.

Loose equality (==): if the types match, it behaves like ===. If they differ, JavaScript applies rules such as: null == undefined, numbers and strings are compared after the string is coerced to a number, booleans are coerced to numbers, and objects are coerced via ToPrimitive when compared with a primitive.

Comparison table

Expression=====
1 == "1"truefalse
0 == falsetruefalse
0 == ""truefalse
"" == falsetruefalse
null == undefinedtruefalse
null == 0falsefalse
null == falsefalsefalse
NaN == NaNfalsefalse
NaN != NaNtruetrue
[] == falsetruefalse
[] == ![]truefalse
[1] == "1"truefalse
{} == {}falsefalse
"0" == falsetruefalse

The NaN gotcha

NaN is never equal to anything, including itself. Both NaN === NaN and NaN == NaN return false, and both NaN !== NaN and NaN != NaN return true. Use Number.isNaN(x) to test for it reliably. The older global isNaN() coerces its argument first, so isNaN("foo") is true — usually not what you want.

The null and undefined relationship

Under loose equality, null and undefined only equal each other and nothing else. So null == undefined is true, but null === undefined is false because their types differ. Crucially, null == 0 is false — the algorithm short-circuits and does not coerce null to a number.

Object equality is reference identity

Both operators compare objects by reference, not by structure. Two distinct object literals with identical contents are never equal:

const a = { x: 1 };
const b = { x: 1 };
a === b; // false
a == b;  // false
a === a; // true

For structural comparison, write a deep-equal helper or use one from a library (Lodash isEqual, Node's assert.deepStrictEqual).

Object.is vs ===

Object.is(a, b) is nearly identical to ===, with two intentional differences:

  • Object.is(NaN, NaN) is true, while NaN === NaN is false.
  • Object.is(+0, -0) is false, while +0 === -0 is true.

Everything else behaves the same. React uses Object.is semantics for its state and dependency comparisons for exactly these reasons.

Modern advice

  1. Default to === and !==. The coercion rules of == are notoriously error-prone and rarely what you actually want.
  2. Use foo == null as an intentional idiom to check for "nullish" values — it matches both null and undefined in a single check and is widely recognized. If you prefer, foo === null || foo === undefined or the nullish coalescing operator foo ?? fallback express the same intent explicitly.
  3. Use Number.isNaN(x) to test for NaN, or Object.is(x, NaN).
  4. Never rely on == for numeric-string comparisons. Convert explicitly with Number(str) or parseInt(str, 10).

Enforce it with ESLint

The eqeqeq rule flags every use of == and !=. Enable it in your config:

// .eslintrc.json
{
  "rules": {
    "eqeqeq": ["error", "always", { "null": "ignore" }]
  }
}

The { "null": "ignore" } option keeps the useful foo == null idiom while blocking every other loose comparison. This pairing — strict equality everywhere plus one deliberate exception — is the pragmatic modern default used by most production JavaScript and TypeScript codebases today.

javascript equality double equals triple equals strict equality loose equality type coercion Object.is eqeqeq

Explore 300+ Free Tools

Utilko has tools for developers, writers, designers, students, and everyday users — all free, all browser-based.