Strict equality in JavaScript: what === really compares

Strict equality compares value and type with no conversion at all. Its two exceptions, and why two identical objects are never equal.
3 min read
Believemy logo

This is the comparison operator recommended everywhere, and rightly so. It still holds two surprises: a number that is not equal to itself, and two identical objects the language calls different.


Definition

Strict equality, written with three equals signs, compares two values without performing any conversion. When the types differ, the answer is immediately false, without even looking at the contents.

JAVASCRIPT
console.log("2" === 2);   // false: string against a number
console.log(2 === 2);      // true
console.log(null === undefined); // false

// The opposite is written !==
console.log("2" !== 2);   // true

This is exactly what separates it from Loose equality (==), which converts before comparing and produces results that are hard to predict. The rule agreed across the profession fits in one sentence: always use three equals signs, except in the one case described on the loose equality page.


The two values that escape the rule

Two cases defy intuition, and both come from the floating-point number standard.

JAVASCRIPT
console.log(NaN === NaN);  // false
console.log(0 === -0);     // true

// The right way to test each of them
console.log(Number.isNaN(NaN));  // true
console.log(Object.is(0, -0));   // false

NaN stands for a numeric calculation that failed, and two failures have no reason to be the same failure: it equals nothing, not even itself. Negative zero, on the other hand, is genuinely distinct from positive zero in memory, yet strict equality merges them.

Good to know

Object.is answers exactly like strict equality, apart from those two exceptions, which it handles the other way round. Useful there, pointless elsewhere.


Objects are compared by address

Here is the point that costs beginners the most time. On an object, an array or a function, the operator does not look at the contents: it asks whether this is the same instance in memory.

JAVASCRIPT
const a = [1, 2];
const b = [1, 2];
const c = a;

console.log(a === b); // false: two separate arrays
console.log(a === c); // true:  the same array

// Comparing contents takes another approach
console.log(JSON.stringify(a) === JSON.stringify(b)); // true

That last line helps on simple data, but it depends on key order and handles neither dates nor functions. For a serious comparison, write a dedicated function or reach for a library.


Frequently asked questions

Question

Should === always be preferred over ==?

Yes, with one exception. Writing value == null tests null and undefined in one go, which is genuinely handy. Everywhere else, three equals signs avoid invisible conversions that produce bugs which are very hard to track down.


Question

How do I compare two objects on their contents?

By comparing their properties one by one, something no operator in the language does for you. On flat structures, a loop over the keys is enough. On nested structures, the comparison turns recursive and deserves a well-tested function rather than something written in a hurry.


Question

Why does 0.1 + 0.2 === 0.3 return false?

Because the addition does not yield exactly 0.3 but a very slightly larger value, a consequence of how decimals are encoded in binary. The operator itself is doing its job correctly. To compare decimals, check that the absolute gap stays below a small tolerance.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.