JavaScript Tutorial

JavaScript Comparison Operators: Complete Guide with Examples

Master JavaScript comparison operators including equality (==, ===), inequality (!=, !==), and relational operators (<, >, <=, >=). Learn the difference between loose and strict equality with practical examples.

Welcome back! 👋 In the previous lessons, you learned about arithmetic and assignment operators. Now, let's explore comparison operators - operators that compare two values and return a boolean result (true or false).

Comparison operators are essential for making decisions in your code. They're used in conditional statements, loops, and anywhere you need to compare values. Let's master them!


What are Comparison Operators?

Comparison operators compare two values and return a boolean result: true or false.

let a = 10;
let b = 5;

console.log(a > b);   // true - "Is 10 greater than 5?"
console.log(a === b); // false - "Is 10 equal to 5?"
console.log(a < b);   // false - "Is 10 less than 5?"

These operators are the foundation of:

  • Conditional statements (if, else, switch)
  • Loop conditions (while, for)
  • Ternary operators (condition ? true : false)
  • Filtering and searching data

Types of Comparison Operators

JavaScript provides two categories of comparison operators:

1. Equality Operators

  • == Loose equality (with type coercion)
  • === Strict equality (no type coercion)
  • != Loose inequality (with type coercion)
  • !== Strict inequality (no type coercion)

2. Relational Operators

  • > Greater than
  • < Less than
  • >= Greater than or equal to
  • <= Less than or equal to

Let's explore each one in detail!


Equality Operators


Strict Equality (===)

The strict equality operator checks if two values are equal without type conversion. Both the value AND type must be the same.

Syntax

operand1 === operand2

Why Use === (The Good One)

Always prefer === over == - it's more predictable and prevents bugs caused by type coercion.

// Type and value must match
console.log(5 === 5);          // true
console.log("hello" === "hello"); // true
console.log(true === true);    // true

// Different types = false (no conversion)
console.log(5 === "5");        // false (number vs string)
console.log(0 === false);      // false (number vs boolean)
console.log(null === undefined); // false (different types)

Examples with Different Types

// Numbers
console.log(10 === 10);        // true
console.log(10 === 10.0);      // true (same value)
console.log(10 === 20);        // false

// Strings
console.log("hello" === "hello");   // true
console.log("hello" === "Hello");   // false (case-sensitive)
console.log("10" === "10");         // true

// Booleans
console.log(true === true);    // true
console.log(false === false);  // true
console.log(true === false);   // false

// null and undefined
console.log(null === null);         // true
console.log(undefined === undefined); // true
console.log(null === undefined);    // false (different types!)

// Special case: NaN
console.log(NaN === NaN);      // false (NaN is never equal to itself!)

// Type mismatch
console.log(5 === "5");        // false
console.log(1 === true);       // false
console.log(0 === false);      // false
console.log("" === false);     // false

Comparing Objects and Arrays

Important: Objects and arrays are compared by reference, not by content!

// Arrays - compared by reference
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
let arr3 = arr1;

console.log(arr1 === arr2);    // false (different arrays in memory)
console.log(arr1 === arr3);    // true (same reference)

// Objects - compared by reference
let obj1 = { name: "John" };
let obj2 = { name: "John" };
let obj3 = obj1;

console.log(obj1 === obj2);    // false (different objects)
console.log(obj1 === obj3);    // true (same reference)

// Even empty objects/arrays
console.log({} === {});        // false (different objects)
console.log([] === []);        // false (different arrays)

Practical Examples

// User authentication
function login(username, password) {
  const correctUsername = "admin";
  const correctPassword = "secret123";
  
  if (username === correctUsername && password === correctPassword) {
    return "Login successful!";
  }
  return "Invalid credentials";
}

console.log(login("admin", "secret123")); // "Login successful!"
console.log(login("admin", "wrong"));     // "Invalid credentials"

// Type validation
function processNumber(value) {
  if (typeof value === "number") {
    return value * 2;
  }
  return "Not a number";
}

console.log(processNumber(10));    // 20
console.log(processNumber("10"));  // "Not a number"

// Checking enum values
const STATUS = {
  PENDING: "pending",
  APPROVED: "approved",
  REJECTED: "rejected"
};

function getStatusMessage(status) {
  if (status === STATUS.APPROVED) {
    return "Your request has been approved";
  } else if (status === STATUS.REJECTED) {
    return "Your request has been rejected";
  }
  return "Your request is pending";
}

console.log(getStatusMessage(STATUS.APPROVED)); // "Your request has been approved"

// Comparing selected option
let selectedColor = "red";

if (selectedColor === "red") {
  console.log("You selected red");
} else if (selectedColor === "blue") {
  console.log("You selected blue");
}

Loose Equality (==)

The loose equality operator checks if two values are equal with type conversion (coercion).

Syntax

operand1 == operand2

⚠️ Why You Should Avoid ==

Loose equality performs type coercion, which can lead to unexpected and confusing results. Use === instead.

// Type coercion happens
console.log(5 == "5");         // true (string "5" converts to number 5)
console.log(0 == false);       // true (false converts to 0)
console.log(1 == true);        // true (true converts to 1)
console.log("" == false);      // true (both convert to 0)
console.log(null == undefined); // true (special rule)

// Compare with ===
console.log(5 === "5");        // false (no conversion)
console.log(0 === false);      // false
console.log(1 === true);       // false

The Confusing Cases

// These are all TRUE with == (confusing!)
console.log(0 == false);       // true
console.log(0 == "");          // true
console.log(0 == "0");         // true
console.log(false == "");      // true
console.log(false == "0");     // true
console.log("" == "0");        // false (wait, what?!)

// Even more confusing
console.log(" " == false);     // true
console.log("  " == 0);        // true
console.log([0] == false);     // true
console.log([] == false);      // true
console.log([] == 0);          // true
console.log("" == []);         // true

// null and undefined
console.log(null == undefined); // true (only case == is useful)
console.log(null == 0);        // false (doesn't convert to 0)
console.log(undefined == 0);   // false

Type Coercion Rules (How == Works)

When comparing different types with ==, JavaScript follows these rules:

  1. String and Number: String converts to Number
console.log("5" == 5);   // true ("5" → 5)
  1. Boolean and anything: Boolean converts to Number
console.log(true == 1);  // true (true → 1)
console.log(false == 0); // true (false → 0)
  1. null and undefined: Special case - they equal each other
console.log(null == undefined); // true (special rule)
console.log(null == 0);         // false (no conversion)
  1. Object and Primitive: Object converts to primitive
console.log([1] == 1);   // true ([1] → "1" → 1)
console.log([1,2] == "1,2"); // true ([1,2] → "1,2")

The ONLY Acceptable Use of ==

// Checking for null OR undefined (both at once)
let value = null;

// Using ==
if (value == null) {
  console.log("Value is null or undefined");
}

// Equivalent to (but shorter):
if (value === null || value === undefined) {
  console.log("Value is null or undefined");
}

// This is the ONLY recommended use of ==

Why Always Use === Instead

// ❌ Bad - using ==
function isZero(value) {
  return value == 0;  // Will match 0, "0", false, "", []
}

console.log(isZero(0));       // true ✅
console.log(isZero("0"));     // true ⚠️ unexpected
console.log(isZero(false));   // true ⚠️ unexpected
console.log(isZero(""));      // true ⚠️ unexpected

// ✅ Good - using ===
function isZero(value) {
  return value === 0;  // Only matches 0
}

console.log(isZero(0));       // true ✅
console.log(isZero("0"));     // false ✅
console.log(isZero(false));   // false ✅
console.log(isZero(""));      // false ✅

Strict Inequality (!==)

The strict inequality operator is the opposite of ===. Returns true if values are not equal or different types.

Syntax

operand1 !== operand2

Examples

// Different values
console.log(5 !== 10);         // true
console.log("hello" !== "world"); // true
console.log(true !== false);   // true

// Same values
console.log(5 !== 5);          // false
console.log("hello" !== "hello"); // false

// Different types (no conversion)
console.log(5 !== "5");        // true (different types)
console.log(0 !== false);      // true (different types)
console.log(null !== undefined); // true (different types)

// Special case: NaN
console.log(NaN !== NaN);      // true (NaN is not equal to itself)

Practical Examples

// Input validation
function validateAge(age) {
  if (typeof age !== "number") {
    return "Age must be a number";
  }
  if (age !== Math.floor(age)) {
    return "Age must be a whole number";
  }
  if (age < 0) {
    return "Age cannot be negative";
  }
  return "Valid age";
}

console.log(validateAge(25));      // "Valid age"
console.log(validateAge("25"));    // "Age must be a number"
console.log(validateAge(25.5));    // "Age must be a whole number"

// Checking if value changed
let previousValue = 10;
let currentValue = 10;

if (currentValue !== previousValue) {
  console.log("Value changed!");
  updateDisplay();
}

// Filtering array
let users = [
  { id: 1, name: "John", role: "admin" },
  { id: 2, name: "Jane", role: "user" },
  { id: 3, name: "Bob", role: "user" }
];

let nonAdmins = users.filter(user => user.role !== "admin");
console.log(nonAdmins); // Jane and Bob

// Guard clause
function processData(data) {
  if (data !== null && data !== undefined) {
    // Process data
    return data.toUpperCase();
  }
  return "No data provided";
}

Loose Inequality (!=)

The loose inequality operator is the opposite of ==. Returns true if values are not equal after type coercion.

Syntax

operand1 != operand2

Why Avoid !=

Just like ==, the != operator performs type coercion and can produce unexpected results. Use !== instead.

// Type coercion happens
console.log(5 != "5");         // false (string "5" converts to 5)
console.log(0 != false);       // false (both convert to 0)
console.log(null != undefined); // false (special rule)

// Compare with !==
console.log(5 !== "5");        // true (different types)
console.log(0 !== false);      // true (different types)
console.log(null !== undefined); // true (different types)

// Confusing cases
console.log(1 != true);        // false (both become 1)
console.log("0" != 0);         // false (string converts to 0)
console.log("" != false);      // false (both become 0)

Recommendation

// ❌ Avoid != 
if (value != null) {
  // ...
}

// ✅ Use !== instead
if (value !== null && value !== undefined) {
  // ...
}

// ✅ Or use === with logical OR
if (value === null || value === undefined) {
  // ...
}

Relational Operators


Greater Than (>)

The greater than operator returns true if the left operand is greater than the right operand.

Syntax

operand1 > operand2

Examples with Numbers

// Basic comparisons
console.log(10 > 5);           // true
console.log(5 > 10);           // false
console.log(10 > 10);          // false (not greater, just equal)

// Negative numbers
console.log(-5 > -10);         // true (-5 is greater than -10)
console.log(-10 > -5);         // false

// Decimals
console.log(3.5 > 3);          // true
console.log(3.14 > 3.14);      // false (equal)

// Zero
console.log(0 > -1);           // true
console.log(-1 > 0);           // false

String Comparison (Lexicographical)

Strings are compared character by character using Unicode values.

// Alphabetical order
console.log("b" > "a");        // true
console.log("apple" > "banana"); // false (a < b)
console.log("cat" > "car");    // true (t > r)

// Case matters (uppercase < lowercase)
console.log("A" > "a");        // false (A=65, a=97 in Unicode)
console.log("Z" > "a");        // false (Z=90, a=97)

// Number strings (lexicographical!)
console.log("10" > "9");       // false! ("1" < "9" in strings)
console.log("2" > "12");       // true! ("2" > "1" in strings)

// Length doesn't matter, compares character by character
console.log("aa" > "a");       // true (when first chars equal, longer wins)
console.log("abc" > "abd");    // false (c < d)

Type Coercion with >

// String to Number conversion
console.log("10" > 5);         // true ("10" → 10)
console.log("5" > "10");       // true (string comparison! "5" > "1")
console.log(5 > "10");         // false (number comparison, "10" → 10)

// Boolean to Number
console.log(true > false);     // true (1 > 0)
console.log(true > 0);         // true (1 > 0)
console.log(false > -1);       // true (0 > -1)

// Invalid conversions
console.log("hello" > 5);      // false (NaN > 5 = false)
console.log(5 > "hello");      // false (5 > NaN = false)

// null and undefined
console.log(null > 0);         // false (null → 0, so 0 > 0)
console.log(undefined > 0);    // false (undefined → NaN)

Practical Examples

// Age verification
function canVote(age) {
  return age > 17;  // Must be 18 or older
}

console.log(canVote(18));  // true
console.log(canVote(17));  // false

// Score ranking
function getGrade(score) {
  if (score > 90) return "A";
  if (score > 80) return "B";
  if (score > 70) return "C";
  if (score > 60) return "D";
  return "F";
}

console.log(getGrade(95));  // "A"
console.log(getGrade(85));  // "B"

// Price filtering
let products = [
  { name: "Book", price: 15 },
  { name: "Phone", price: 500 },
  { name: "Laptop", price: 1000 }
];

let expensive = products.filter(p => p.price > 100);
console.log(expensive); // Phone and Laptop

// Date comparison
let deadline = new Date("2024-12-31");
let today = new Date();

if (today > deadline) {
  console.log("Deadline passed!");
}

Less Than (<)

The less than operator returns true if the left operand is less than the right operand.

Syntax

operand1 < operand2

Examples

// Basic comparisons
console.log(5 < 10);           // true
console.log(10 < 5);           // false
console.log(10 < 10);          // false (not less, just equal)

// Negative numbers
console.log(-10 < -5);         // true
console.log(-5 < -10);         // false

// String comparison
console.log("a" < "b");        // true
console.log("apple" < "banana"); // true
console.log("cat" < "car");    // false (t > r)

// Number strings (lexicographical!)
console.log("9" < "10");       // false! ("9" > "1")
console.log("2" < "12");       // false! ("2" > "1")

Practical Examples

// Minimum value check
function isValidDiscount(discount) {
  return discount < 100;  // Can't be 100% or more
}

console.log(isValidDiscount(50));   // true
console.log(isValidDiscount(100));  // false

// Range check (lower bound)
function isInRange(value, min, max) {
  return value > min && value < max;
}

console.log(isInRange(5, 0, 10));   // true
console.log(isInRange(15, 0, 10));  // false

// Priority queue
let tasks = [
  { name: "Task A", priority: 1 },
  { name: "Task B", priority: 3 },
  { name: "Task C", priority: 2 }
];

let urgent = tasks.filter(t => t.priority < 2);
console.log(urgent); // Task A

// Stock alert
function checkStock(quantity, threshold) {
  if (quantity < threshold) {
    return "Low stock! Reorder needed.";
  }
  return "Stock level OK";
}

console.log(checkStock(5, 10));   // "Low stock! Reorder needed."
console.log(checkStock(15, 10));  // "Stock level OK"

Greater Than or Equal To (>=)

Returns true if the left operand is greater than or equal to the right operand.

Syntax

operand1 >= operand2

Examples

// Basic comparisons
console.log(10 >= 5);          // true (greater)
console.log(10 >= 10);         // true (equal)
console.log(5 >= 10);          // false (less)

// Negative numbers
console.log(-5 >= -10);        // true
console.log(-10 >= -10);       // true (equal)

// String comparison
console.log("b" >= "a");       // true
console.log("a" >= "a");       // true (equal)
console.log("apple" >= "apple"); // true (equal)

// Type coercion
console.log("10" >= 10);       // true
console.log(10 >= "10");       // true
console.log(true >= 1);        // true (true → 1)

Practical Examples

// Age eligibility
function canRetire(age) {
  return age >= 65;
}

console.log(canRetire(65));  // true
console.log(canRetire(70));  // true
console.log(canRetire(64));  // false

// Grade passing
function isPassing(score) {
  return score >= 60;
}

console.log(isPassing(60));  // true
console.log(isPassing(75));  // true
console.log(isPassing(59));  // false

// Minimum purchase for free shipping
function qualifiesForFreeShipping(total) {
  const MINIMUM = 50;
  return total >= MINIMUM;
}

console.log(qualifiesForFreeShipping(50));   // true
console.log(qualifiesForFreeShipping(75));   // true
console.log(qualifiesForFreeShipping(49.99)); // false

// Access level check
const ACCESS_LEVELS = {
  GUEST: 0,
  USER: 1,
  MODERATOR: 2,
  ADMIN: 3
};

function canDeletePost(userLevel) {
  return userLevel >= ACCESS_LEVELS.MODERATOR;
}

console.log(canDeletePost(ACCESS_LEVELS.ADMIN));     // true
console.log(canDeletePost(ACCESS_LEVELS.MODERATOR)); // true
console.log(canDeletePost(ACCESS_LEVELS.USER));      // false

Less Than or Equal To (<=)

Returns true if the left operand is less than or equal to the right operand.

Syntax

operand1 <= operand2

Examples

// Basic comparisons
console.log(5 <= 10);          // true (less)
console.log(10 <= 10);         // true (equal)
console.log(15 <= 10);         // false (greater)

// Negative numbers
console.log(-10 <= -5);        // true
console.log(-5 <= -5);         // true (equal)

// String comparison
console.log("a" <= "b");       // true
console.log("a" <= "a");       // true (equal)
console.log("banana" <= "apple"); // false

// Type coercion
console.log("10" <= 10);       // true
console.log(10 <= "10");       // true
console.log(false <= 0);       // true (false → 0)

Practical Examples

// Maximum capacity
function canAccommodate(guests, capacity) {
  return guests <= capacity;
}

console.log(canAccommodate(50, 100));  // true
console.log(canAccommodate(100, 100)); // true
console.log(canAccommodate(150, 100)); // false

// Budget check
function isWithinBudget(price, budget) {
  return price <= budget;
}

console.log(isWithinBudget(50, 100));   // true
console.log(isWithinBudget(100, 100));  // true
console.log(isWithinBudget(150, 100));  // false

// Character limit
function isValidUsername(username, maxLength) {
  return username.length <= maxLength;
}

console.log(isValidUsername("john", 10));     // true
console.log(isValidUsername("johndoe", 10));  // true
console.log(isValidUsername("verylongusername", 10)); // false

// Temperature warning
function isSafeTemperature(temp) {
  const MAX_SAFE_TEMP = 100;
  return temp <= MAX_SAFE_TEMP;
}

console.log(isSafeTemperature(80));   // true
console.log(isSafeTemperature(100));  // true
console.log(isSafeTemperature(110));  // false

Special Cases and Gotchas

Comparing NaN

NaN is never equal to anything, including itself!

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

// All comparisons with NaN return false
console.log(NaN > 5);          // false
console.log(NaN < 5);          // false
console.log(NaN >= 5);         // false
console.log(NaN <= 5);         // false

// How to check for NaN
let result = "hello" * 2;
console.log(result === NaN);   // false (doesn't work!)
console.log(isNaN(result));    // true ✅
console.log(Number.isNaN(result)); // true ✅ (more reliable)

Comparing null and undefined

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

// With ==
console.log(null == undefined);     // true (only case == is useful)
console.log(null == null);          // true
console.log(undefined == undefined); // true

// With relational operators (weird!)
console.log(null > 0);         // false (null → 0)
console.log(null == 0);        // false (special rule)
console.log(null >= 0);        // true (null → 0) ⚠️ Confusing!

console.log(undefined > 0);    // false (undefined → NaN)
console.log(undefined < 0);    // false (undefined → NaN)
console.log(undefined == 0);   // false

Comparing Objects and Arrays

Objects and arrays are compared by reference, not by content.

// Different arrays (even with same content)
console.log([1, 2, 3] === [1, 2, 3]);  // false
console.log([1, 2, 3] == [1, 2, 3]);   // false

// Same reference
let arr = [1, 2, 3];
let sameArr = arr;
console.log(arr === sameArr);          // true

// Objects
console.log({ a: 1 } === { a: 1 });   // false
console.log({ } === { });             // false

let obj = { a: 1 };
let sameObj = obj;
console.log(obj === sameObj);          // true

// To compare content, use JSON.stringify or custom function
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)); // true

String Comparison Gotchas

// Case sensitivity
console.log("apple" === "Apple");  // false
console.log("hello" === "HELLO");  // false

// Number strings (lexicographical order!)
console.log("10" > "9");       // false! ("1" < "9")
console.log("2" > "10");       // true! ("2" > "1")
console.log("100" < "20");     // true! ("1" < "2")

// Solution: Convert to numbers
console.log(Number("10") > Number("9"));   // true
console.log(parseInt("10") > parseInt("9")); // true

// Unicode comparison
console.log("A" < "a");        // true (65 < 97)
console.log("Z" < "a");        // true (90 < 97)

// Comparing with empty string
console.log("" < "a");         // true (empty is "smallest")
console.log("" === "");        // true

Type Coercion Surprises

// Boolean comparisons
console.log(true == 1);        // true (true → 1)
console.log(false == 0);       // true (false → 0)
console.log(true === 1);       // false (different types)

// Array to primitive
console.log([1] == 1);         // true ([1] → "1" → 1)
console.log([1, 2] == "1,2");  // true ([1,2] → "1,2")
console.log([] == 0);          // true ([] → "" → 0)
console.log([] == false);      // true

// String with whitespace
console.log(" " == 0);         // true (" " → 0)
console.log("  " == false);    // true ("  " → 0 → false)
console.log(" " === 0);        // false (different types)

Combining Comparison Operators

Range Checks

// Check if value is within range
function isInRange(value, min, max) {
  return value >= min && value <= max;
}

console.log(isInRange(5, 1, 10));   // true
console.log(isInRange(0, 1, 10));   // false
console.log(isInRange(10, 1, 10));  // true

// Age groups
function getAgeGroup(age) {
  if (age < 13) return "Child";
  if (age >= 13 && age < 20) return "Teenager";
  if (age >= 20 && age < 65) return "Adult";
  return "Senior";
}

console.log(getAgeGroup(10));   // "Child"
console.log(getAgeGroup(16));   // "Teenager"
console.log(getAgeGroup(30));   // "Adult"
console.log(getAgeGroup(70));   // "Senior"

Multiple Conditions

// Login validation
function canLogin(username, password, isActive) {
  return username !== "" && 
         password !== "" && 
         password.length >= 8 && 
         isActive === true;
}

console.log(canLogin("john", "password123", true));  // true
console.log(canLogin("", "password123", true));      // false
console.log(canLogin("john", "short", true));        // false
console.log(canLogin("john", "password123", false)); // false

// Discount eligibility
function getDiscount(totalAmount, isMember, itemCount) {
  if (totalAmount >= 100 && isMember) {
    return 0.2;  // 20% off
  } else if (totalAmount >= 100 || itemCount >= 5) {
    return 0.1;  // 10% off
  }
  return 0;  // No discount
}

console.log(getDiscount(150, true, 2));   // 0.2
console.log(getDiscount(150, false, 2));  // 0.1
console.log(getDiscount(50, false, 6));   // 0.1
console.log(getDiscount(50, false, 2));   // 0

Common Mistakes and Pitfalls

Mistake 1: Using == Instead of ===

// ❌ Bad - type coercion surprises
if (userInput == 0) {
  console.log("Zero");  // Also matches "", false, "0", []
}

// ✅ Good - explicit type check
if (userInput === 0) {
  console.log("Zero");  // Only matches 0
}

Mistake 2: Comparing Objects/Arrays by Value

// ❌ Bad - compares references, not content
if (user === { name: "John", age: 30 }) {
  console.log("Match");  // Never runs!
}

// ✅ Good - compare properties
if (user.name === "John" && user.age === 30) {
  console.log("Match");
}

// ✅ Or use JSON.stringify for simple cases
if (JSON.stringify(user) === JSON.stringify({ name: "John", age: 30 })) {
  console.log("Match");
}

Mistake 3: String Number Comparison

// ❌ Bad - string comparison, not numeric
let userAge = "25";
if (userAge > 18) {
  console.log("Adult");  // Works, but risky
}

if (userAge > "100") {
  console.log("Very old");  // WRONG! "25" > "100" is true
}

// ✅ Good - convert to number first
let age = Number(userAge);
if (age > 18) {
  console.log("Adult");
}

if (age > 100) {
  console.log("Very old");  // Correct numeric comparison
}

Mistake 4: Checking for NaN

// ❌ Bad - doesn't work
let result = "hello" * 2;
if (result === NaN) {
  console.log("Not a number");  // Never runs!
}

// ✅ Good - use isNaN or Number.isNaN
if (Number.isNaN(result)) {
  console.log("Not a number");
}

Mistake 5: Chaining Comparisons

// ❌ Bad - doesn't work as expected
let x = 5;
if (3 < x < 7) {
  console.log("Between 3 and 7");  // Always true! Why?
}

// How it's evaluated:
// (3 < x) < 7
// (3 < 5) < 7
// true < 7
// 1 < 7
// true

// ✅ Good - use logical operators
if (3 < x && x < 7) {
  console.log("Between 3 and 7");
}

// ✅ Or create a function
function isBetween(value, min, max) {
  return value > min && value < max;
}

if (isBetween(x, 3, 7)) {
  console.log("Between 3 and 7");
}

Mistake 6: Null/Undefined Comparison

// ❌ Confusing behavior
console.log(null > 0);     // false
console.log(null == 0);    // false
console.log(null >= 0);    // true (WTF?!)

// ✅ Be explicit with null/undefined checks
if (value === null || value === undefined) {
  console.log("No value");
}

// ✅ Or use the == null pattern
if (value == null) {  // Checks both null and undefined
  console.log("No value");
}

Best Practices

1. Always Use === and !== (Strict Equality)

// ❌ Bad
if (value == "10") { }
if (flag != false) { }

// ✅ Good
if (value === "10") { }
if (flag !== false) { }

// ✅ Exception: Checking for null/undefined
if (value == null) {  // This is okay
  // value is null OR undefined
}

2. Convert Types Explicitly

// ❌ Bad - relying on coercion
if ("5" > 3) { }

// ✅ Good - explicit conversion
if (Number("5") > 3) { }
if (parseInt("5") > 3) { }

3. Use Descriptive Comparison Functions

// ❌ Hard to understand
if (user.age >= 18 && user.age < 65 && user.income > 30000) { }

// ✅ Clear and reusable
function isWorkingAge(age) {
  return age >= 18 && age < 65;
}

function hasMinimumIncome(income) {
  return income > 30000;
}

if (isWorkingAge(user.age) && hasMinimumIncome(user.income)) { }

4. Handle Edge Cases

// ❌ Doesn't handle all cases
function compareValues(a, b) {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
}

// What about NaN, null, undefined?

// ✅ Handle edge cases
function compareValues(a, b) {
  if (a == null || b == null) return NaN;
  if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
}

5. Use Constants for Magic Numbers

// ❌ Magic numbers
if (age >= 18) { }
if (score > 90) { }

// ✅ Named constants
const ADULT_AGE = 18;
const GRADE_A_THRESHOLD = 90;

if (age >= ADULT_AGE) { }
if (score > GRADE_A_THRESHOLD) { }

6. Avoid Comparing Different Types

// ❌ Bad - comparing different types
if (userId === "123") {  // userId might be number or string
  // ...
}

// ✅ Good - ensure same type
if (String(userId) === "123") {
  // ...
}

// ✅ Or compare both as numbers
if (Number(userId) === 123) {
  // ...
}

Practical Examples

Example 1: Form Validation

function validateRegistration(userData) {
  const errors = [];
  
  // Username validation
  if (userData.username === "" || userData.username == null) {
    errors.push("Username is required");
  } else if (userData.username.length < 3) {
    errors.push("Username must be at least 3 characters");
  }
  
  // Email validation (simple)
  if (userData.email === "" || userData.email == null) {
    errors.push("Email is required");
  } else if (!userData.email.includes("@")) {
    errors.push("Invalid email format");
  }
  
  // Age validation
  if (userData.age == null) {
    errors.push("Age is required");
  } else if (typeof userData.age !== "number") {
    errors.push("Age must be a number");
  } else if (userData.age < 18) {
    errors.push("Must be 18 or older");
  } else if (userData.age > 120) {
    errors.push("Invalid age");
  }
  
  // Password validation
  if (userData.password === "" || userData.password == null) {
    errors.push("Password is required");
  } else if (userData.password.length < 8) {
    errors.push("Password must be at least 8 characters");
  }
  
  return {
    valid: errors.length === 0,
    errors: errors
  };
}

// Test
let result1 = validateRegistration({
  username: "john",
  email: "john@example.com",
  age: 25,
  password: "password123"
});
console.log(result1);  // { valid: true, errors: [] }

let result2 = validateRegistration({
  username: "jo",
  email: "invalid",
  age: 15,
  password: "short"
});
console.log(result2);
// {
//   valid: false,
//   errors: [
//     "Username must be at least 3 characters",
//     "Invalid email format",
//     "Must be 18 or older",
//     "Password must be at least 8 characters"
//   ]
// }

Example 2: Sorting and Filtering

let products = [
  { id: 1, name: "Laptop", price: 999, rating: 4.5, inStock: true },
  { id: 2, name: "Mouse", price: 25, rating: 4.2, inStock: true },
  { id: 3, name: "Keyboard", price: 75, rating: 4.7, inStock: false },
  { id: 4, name: "Monitor", price: 299, rating: 4.4, inStock: true },
  { id: 5, name: "Webcam", price: 89, rating: 3.9, inStock: true }
];

// Filter: In stock, price <= 100, rating >= 4.0
let affordable = products.filter(p => 
  p.inStock === true && 
  p.price <= 100 && 
  p.rating >= 4.0
);
console.log(affordable);  // Mouse, Webcam

// Sort by price (low to high)
let sortedByPrice = [...products].sort((a, b) => {
  if (a.price < b.price) return -1;
  if (a.price > b.price) return 1;
  return 0;
});

// Find first product over $500
let expensive = products.find(p => p.price > 500);
console.log(expensive);  // Laptop

// Check if all in-stock items are under $1000
let allAffordable = products
  .filter(p => p.inStock === true)
  .every(p => p.price < 1000);
console.log(allAffordable);  // true

Example 3: Access Control

const ROLES = {
  GUEST: 0,
  USER: 1,
  MODERATOR: 2,
  ADMIN: 3
};

const PERMISSIONS = {
  READ: 0,
  WRITE: 1,
  DELETE: 2,
  MANAGE_USERS: 3
};

function hasPermission(userRole, requiredPermission) {
  if (userRole === ROLES.ADMIN) {
    return true;  // Admin has all permissions
  }
  
  if (requiredPermission === PERMISSIONS.READ) {
    return userRole >= ROLES.USER;
  }
  
  if (requiredPermission === PERMISSIONS.WRITE) {
    return userRole >= ROLES.USER;
  }
  
  if (requiredPermission === PERMISSIONS.DELETE) {
    return userRole >= ROLES.MODERATOR;
  }
  
  if (requiredPermission === PERMISSIONS.MANAGE_USERS) {
    return userRole >= ROLES.ADMIN;
  }
  
  return false;
}

// Test
console.log(hasPermission(ROLES.GUEST, PERMISSIONS.READ));       // false
console.log(hasPermission(ROLES.USER, PERMISSIONS.READ));        // true
console.log(hasPermission(ROLES.USER, PERMISSIONS.DELETE));      // false
console.log(hasPermission(ROLES.MODERATOR, PERMISSIONS.DELETE)); // true
console.log(hasPermission(ROLES.ADMIN, PERMISSIONS.MANAGE_USERS)); // true

Example 4: Date Comparison

function isDateInRange(date, startDate, endDate) {
  return date >= startDate && date <= endDate;
}

function getDaysUntil(targetDate) {
  const today = new Date();
  const target = new Date(targetDate);
  const diffTime = target - today;
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  return diffDays;
}

function isExpired(expiryDate) {
  const today = new Date();
  return new Date(expiryDate) < today;
}

// Test
let today = new Date();
let nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);
let lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);

console.log(isDateInRange(today, lastWeek, nextWeek));  // true
console.log(getDaysUntil("2024-12-31"));  // Days until end of year
console.log(isExpired("2024-01-01"));  // Check if date has passed

Practice Exercises

Create a file called comparison-practice.js:

// Comparison Operators Practice

// Exercise 1: Grade Calculator
function calculateLetterGrade(score) {
  // TODO: Return letter grade based on score
  // A: 90-100, B: 80-89, C: 70-79, D: 60-69, F: below 60
  // Handle invalid input (not a number, negative, > 100)
}

// Test
console.log(calculateLetterGrade(95));   // "A"
console.log(calculateLetterGrade(85));   // "B"
console.log(calculateLetterGrade(55));   // "F"
console.log(calculateLetterGrade(-5));   // "Invalid score"
console.log(calculateLetterGrade(150));  // "Invalid score"

// Exercise 2: Password Strength Checker
function checkPasswordStrength(password) {
  // TODO: Return "weak", "medium", or "strong"
  // Weak: < 8 characters
  // Medium: 8-12 characters
  // Strong: > 12 characters AND has number AND has special char
}

// Test
console.log(checkPasswordStrength("short"));        // "weak"
console.log(checkPasswordStrength("password123"));  // "medium"
console.log(checkPasswordStrength("MyP@ssw0rd!"));  // "strong"

// Exercise 3: Age Category
function getAgeCategory(age) {
  // TODO: Return age category
  // Baby: 0-2, Child: 3-12, Teen: 13-19, Adult: 20-64, Senior: 65+
  // Handle invalid input
}

// Test
console.log(getAgeCategory(1));    // "Baby"
console.log(getAgeCategory(10));   // "Child"
console.log(getAgeCategory(16));   // "Teen"
console.log(getAgeCategory(30));   // "Adult"
console.log(getAgeCategory(70));   // "Senior"

// Exercise 4: Leap Year Checker
function isLeapYear(year) {
  // TODO: Check if year is a leap year
  // Divisible by 4 AND (not divisible by 100 OR divisible by 400)
}

// Test
console.log(isLeapYear(2024));  // true
console.log(isLeapYear(2023));  // false
console.log(isLeapYear(2000));  // true
console.log(isLeapYear(1900));  // false

// Exercise 5: Array Comparison
function arraysEqual(arr1, arr2) {
  // TODO: Check if two arrays have same content
  // Return true only if same length and all elements match
}

// Test
console.log(arraysEqual([1, 2, 3], [1, 2, 3]));     // true
console.log(arraysEqual([1, 2, 3], [1, 2, 4]));     // false
console.log(arraysEqual([1, 2], [1, 2, 3]));        // false
console.log(arraysEqual([], []));                   // true

// Exercise 6: Safe Comparison
function safeCompare(a, b) {
  // TODO: Compare two values safely
  // Handle null, undefined, NaN
  // Return: -1 (a < b), 0 (a === b), 1 (a > b), NaN (can't compare)
}

// Test
console.log(safeCompare(5, 10));          // -1
console.log(safeCompare(10, 10));         // 0
console.log(safeCompare(15, 10));         // 1
console.log(safeCompare(null, 5));        // NaN
console.log(safeCompare(NaN, 5));         // NaN

Summary

Congratulations! 🎉 You now have a comprehensive understanding of comparison operators in JavaScript.

Key Takeaways

Equality Operators:

  • === Strict equality (recommended) - checks type AND value
  • == Loose equality (avoid) - performs type coercion
  • !== Strict inequality (recommended)
  • != Loose inequality (avoid)

Relational Operators:

  • > Greater than
  • < Less than
  • >= Greater than or equal to
  • <= Less than or equal to

Best Practices:

  • Always use === and !== (strict equality)
  • Only use == for checking null/undefined: value == null
  • Convert types explicitly before comparing
  • Be careful with string comparisons (lexicographical order)
  • Objects/arrays are compared by reference, not content

Special Cases:

  • NaN !== NaN (use Number.isNaN() to check)
  • null == undefined is true (only case == is useful)
  • String numbers: "10" > "9" is false (lexicographical!)
  • Objects/arrays: compared by reference, not content

Common Mistakes:

  • Using == instead of ===
  • Comparing objects by value
  • Not converting string numbers
  • Trying to compare NaN with ===
  • Chaining comparisons incorrectly

What's Next?

Excellent work! You now understand how to compare values in JavaScript.

In the next lesson, we'll explore Logical Operators where you'll learn:

  • Logical AND (&&)
  • Logical OR (||)
  • Logical NOT (!)
  • Short-circuit evaluation
  • Nullish coalescing operator (??)
  • Combining logical and comparison operators
  • Truth tables and boolean logic