Equality Operators

JavaScript has two kinds of equality/inequality operators: abstract (==, !=) and strict (===, !==).

Abstract Equality

This operator looks like the one used in languages such as Java and C++:

console.log(2 == 2);  // true
console.log(1 == 2);  // false
console.log(3 != 2);  // true

When the operands are of different types, the abstract equality operator converts the types first.

console.log("2" == 2);  // true
console.log(1 == true);  // true
console.log(0 == false);  // true
console.log("" == false);  // true
console.log("0" == false);  // true (both are converted to 0)

This type conversion makes the equality check more error prone.

Strict Equality

Strict equality uses an extra equal sign. It compares the operands without converting their types.

When the operands have the same type, their value is compared:

console.log(2 === 2);  // true
console.log(1 === 2);  // false
console.log(3 !== 2);  // true

If the operands do not have the same type, then they are considered unequal:

console.log("2" === 2);  // false
console.log(1 === true);  // false
console.log(0 === false);  // false
console.log("" === false);  // false
console.log("0" === false);  // false

Numbers, boolean values, and strings are compared by value. Object and array references are strictly equal only if they refer to the same object in memory:

const student = { name: "John Doe" };
const courseAssistant = { name: "John Doe" };
const headAssistant = courseAssistant;

console.log(student === courseAssistant);  // false
console.log(headAssistant === courseAssistant);  // true

If you need to check value equality of two objects (deep equality), consider using a library like Lodash (_.isEqual) or the lightweight fast-deep-equal package.

Nuances

undefined and null are only equal to themselves, unless you compare them using abstract equality.

console.log(undefined === undefined);  // true
console.log(null === null);  // true
console.log(undefined === null);  // false
console.log(undefined == null);  // true

NaN is not equal to NaN, no matter which equality operator you use.

console.log(NaN == NaN);  // false
console.log(NaN === NaN);  // false

Because of this, JavaScript’s == and === operators are not equivalence relations (since they are not reflexive).

To check whether a variable is NaN, use one of these static methods:

let num = NaN;
console.log(Number.isNaN(num));  // true
console.log(Object.is(num, NaN));  // true

Object.is is a newer addition to JavaScript. It works the same way as strict equality except for NaN and +0/-0.

console.log(+0 === -0);  // true
console.log(Object.is(-0, +0));  // false

JavaScript Object.is is designed to have the properties of an equivalence relation (it is reflexive, symmetric, and transitive).

MDN Web Docs has an article on JavaScript’s “Equality comparisons and sameness” available at this link.