JavaScript
Programming
Coding
Web Development
Computer Science

Difference between == and === in JavaScript

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

JavaScript has two equality operators: == (loose equality) and === (strict equality). The == operator compares values after type coercion, while === compares both value and type without any conversion. Understanding the difference is critical for avoiding subtle bugs.

Strict Equality (===)

=== returns true only if both the value and type are identical. No type conversion occurs:

javascript
15 === 5          // true  (same value, same type)
2"5" === 5        // false (string vs number)
3true === 1       // false (boolean vs number)
4null === undefined // false (different types)
50 === false      // false (number vs boolean)
6"" === false     // false (string vs boolean)
7NaN === NaN      // false (NaN is never equal to anything)

Loose Equality (==)

== performs type coercion before comparing. JavaScript converts one or both operands to a common type:

javascript
15 == 5           // true
2"5" == 5         // true  (string "5" coerced to number 5)
3true == 1        // true  (boolean true coerced to 1)
4false == 0       // true  (boolean false coerced to 0)
5null == undefined // true (special case in the spec)
6"" == false      // true  (both coerce to 0)
7" " == 0         // true  (string " " coerces to 0)

Type Coercion Rules

When == compares different types, it follows these rules:

  1. Number vs String: The string is converted to a number
  2. Boolean vs Anything: The boolean is converted to a number (true→1, false→0)
  3. null vs undefined: They are equal to each other and nothing else
  4. Object vs Primitive: The object's valueOf() or toString() is called
javascript
1// String to Number
2"42" == 42       // true: "42" → 42
3
4// Boolean to Number
5true == 1        // true: true → 1
6false == 0       // true: false → 0
7true == "1"      // true: true → 1, "1" → 1
8
9// null and undefined
10null == undefined   // true (special case)
11null == 0           // false (null only equals undefined)
12null == ""          // false
13undefined == false  // false
14
15// Object to Primitive
16[1] == 1           // true: [1].toString() → "1" → 1
17["5"] == 5         // true: ["5"].toString() → "5" → 5

Surprising Results with ==

javascript
1// All of these are true with ==
2"" == false       // true
3"0" == false      // true
4" " == 0          // true
5[] == false       // true
6[] == 0           // true
7[[]] == 0         // true
8[null] == ""      // true
9
10// The transitive property breaks
11"" == 0           // true
120 == "0"          // true
13"" == "0"         // false! (both are strings, no coercion)

The !== and != Operators

The same distinction applies to inequality:

javascript
1// Strict inequality
25 !== "5"         // true (different types)
35 !== 5           // false
4
5// Loose inequality
65 != "5"          // false (coerced, values are equal)
75 != 5            // false

Best Practice: Always Use ===

The === operator is predictable and avoids coercion bugs:

javascript
1// BAD: subtle bugs
2if (value == null) { }        // matches both null and undefined
3if (value == 0) { }           // matches 0, "", false, null? No, but confusing
4if (response == true) { }     // matches 1, "1", etc.
5
6// GOOD: explicit and clear
7if (value === null || value === undefined) { }
8if (value === 0) { }
9if (response === true) { }

When == Is Acceptable

The only widely accepted use of == is checking for null or undefined:

javascript
1// This is a common pattern even in strict codebases
2if (value == null) {
3    // handles both null and undefined
4}
5
6// Equivalent to:
7if (value === null || value === undefined) {
8    // same behavior, more verbose
9}

ESLint Rules

Most JavaScript linters enforce strict equality:

json
1{
2    "rules": {
3        "eqeqeq": ["error", "always"]
4    }
5}

The eqeqeq rule can be configured to allow == only for null checks:

json
1{
2    "rules": {
3        "eqeqeq": ["error", "always", { "null": "ignore" }]
4    }
5}

Comparison Table

Expression=====
"5" ? 5truefalse
0 ? falsetruefalse
"" ? falsetruefalse
null ? undefinedtruefalse
NaN ? NaNfalsefalse
[1] ? 1truefalse
true ? 1truefalse

Common Pitfalls

  • Truthy/falsy confusion: == and truthy/falsy checks are different things. "0" == false is true, but "0" is truthy in a boolean context (if ("0") is true). Do not conflate them.
  • NaN equality: NaN === NaN is false. Use Number.isNaN() to check for NaN, not ===.
  • Object comparison: Both == and === compare objects by reference, not value. {a:1} === {a:1} is false because they are different objects.
  • typeof check: typeof null === "object" is true (a known JavaScript quirk). Check for null explicitly before using typeof.
  • Automatic coercion in other contexts: Coercion also happens with <, >, +, and other operators. "5" + 3 is "53" (string concatenation), not 8.

Summary

  • === (strict equality) compares value and type — no coercion, no surprises
  • == (loose equality) coerces types before comparing — can produce unexpected results
  • Always use === and !== by default
  • The only acceptable use of == is value == null to check for both null and undefined
  • Enable the eqeqeq ESLint rule to enforce strict equality in your codebase

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.