7  Comparison and Logical Operators

7.1 Comparison Operators

JavaScript’s comparison operators evaluate expressions and return boolean values (true or false). They’re essential for creating conditions in if statements, loops, and anywhere you need to make decisions in your code.

Operator Name Description Example Result
== Equality Compares values, performs type coercion 5 == "5" true
=== Strict equality Compares values and types, no coercion 5 === "5" false
!= Inequality Compares if values are not equal, with coercion 5 != "6" true
!== Strict inequality Compares if values or types are different 5 !== "5" true
> Greater than Checks if left value is greater than right 5 > 3 true
< Less than Checks if left value is less than right 5 < 3 false
>= Greater than or equal Checks if left is greater than or equal to right 5 >= 5 true
<= Less than or equal Checks if left is less than or equal to right 5 <= 5 true

7.1.1 Type Coercion in Comparisons

The non-strict operators (==, !=) perform type coercion, which can sometimes lead to unexpected results:

0 == false         // true (false coerced to 0)
0 === false        // false (different types)
"" == false        // true (both coerced to 0)
"" === false       // false (different types)
null == undefined  // true (special case in JavaScript)
null === undefined // false (different types)

7.1.2 Important Coercion Rules:

  1. When comparing a string with a number, JavaScript converts the string to a number
  2. When comparing a boolean with anything, JavaScript converts the boolean to a number (false → 0, true → 1)
  3. When comparing an object with a primitive, JavaScript attempts to convert the object to a primitive

7.1.3 Best Practice:

Almost all modern JavaScript style guides recommend using the strict equality operators (=== and !==) by default to avoid unexpected behavior from type coercion. Only use loose equality (== and !=) when you specifically want type coercion to occur.

7.2 Logical Operators

Logical operators are used to combine or modify boolean expressions.

Operator Name Description Example Result
&& Logical AND Returns true if both operands are true true && true true
\|\| Logical OR Returns true if either operand is true false \|\| true true
! Logical NOT Returns the opposite boolean value !true false
?? Nullish coalescing Returns right operand if left is null/undefined null ?? "default" "default"

7.2.1 Short-Circuit Evaluation

JavaScript’s logical operators use “short-circuit” evaluation, which means they stop evaluating as soon as the result is determined:

// AND operator - stops at first false value
false && anyExpression  // Returns false without evaluating anyExpression
true && false          // Evaluates both sides, returns false

// OR operator - stops at first true value
true || anyExpression  // Returns true without evaluating anyExpression
false || true          // Evaluates both sides, returns true

7.2.2 Return Values (Not Just Booleans!)

A key point about JavaScript’s logical operators is that they don’t always return boolean values. They return the value of the operand that determined the result:

// AND returns the first falsy value, or the last value if all are truthy
"Hello" && 0 && true  // Returns 0 (first falsy value)
"Hello" && 42 && true  // Returns true (last value, all are truthy)

// OR returns the first truthy value, or the last value if all are falsy
"" || 0 || "Hello"  // Returns "Hello" (first truthy value)
"" || 0 || false  // Returns false (last value, all are falsy)

This behavior enables a common pattern for setting default values:

function greet(name) {
  name = name || "Guest";  // If name is falsy, use "Guest" instead
  return "Hello, " + name;
}

// Modern approach using nullish coalescing
function greetBetter(name) {
  name = name ?? "Guest";  // Only uses "Guest" if name is null or undefined
  return "Hello, " + name;
}

7.2.3 Nullish Coalescing Operator (??)

The nullish coalescing operator (??) is a newer addition to JavaScript (ES2020). It works like the OR operator, but only considers null and undefined as triggering the right-hand side:

0 || "default"      // Returns "default" (0 is falsy)
0 ?? "default"      // Returns 0 (0 is not null or undefined)

"" || "default"     // Returns "default" (empty string is falsy)
"" ?? "default"     // Returns "" (empty string is not null or undefined)

null ?? "default"   // Returns "default"
undefined ?? "default" // Returns "default"

This is particularly useful when you want to provide a default value only when a variable is null or undefined, but want to keep other falsy values like 0 or empty strings.

7.2.4 Logical Assignment Operators

ES2021 introduced logical assignment operators that combine logical operations with assignment:

Operator Description Equivalent to
&&= Logical AND assignment x = x && y
\|\|= Logical OR assignment x = x \|\| y
??= Nullish coalescing assignment x = x ?? y

Examples:

let a = true;
a &&= false;  // Same as: a = a && false (results in false)

let b = false;
b ||= true;   // Same as: b = b || true (results in true)

let c = null;
c ??= "default";  // Same as: c = c ?? "default" (results in "default")

7.3 Comparison and Logical Operators in Practice

Here’s a practical example combining comparison and logical operators in a real-world scenario:

function validateUserInput(username, age, email) {
  // Check if username is provided and at least 3 characters
  const isUsernameValid = username && username.length >= 3;
  
  // Check if age is a number and at least 18
  const isAgeValid = typeof age === 'number' && age >= 18;
  
  // Simple email validation (contains @ and .)
  const isEmailValid = email && email.includes('@') && email.includes('.');
  
  // User is valid if all validations pass
  const isUserValid = isUsernameValid && isAgeValid && isEmailValid;
  
  // Provide feedback on what's invalid
  if (!isUserValid) {
    return {
      valid: false,
      errors: {
        username: !isUsernameValid ? "Username must be at least 3 characters" : null,
        age: !isAgeValid ? "Age must be at least 18" : null,
        email: !isEmailValid ? "Please provide a valid email" : null
      }
    };
  }
  
  return { valid: true };
}

// Example usage
const result = validateUserInput("Jo", 17, "invalid-email");
console.log(result);
// {
//   valid: false,
//   errors: {
//     username: "Username must be at least 3 characters",
//     age: "Age must be at least 18",
//     email: "Please provide a valid email"
//   }
// }

7.4 Comparison with R and Python

Coming from R and Python, these are key differences to be aware of:

  • JavaScript has both strict (===) and loose (==) equality operators, unlike Python’s single ==
  • JavaScript’s logical operators (&&, ||) return the determining value, not just true or false
  • JavaScript’s type coercion rules are more complex than Python’s
  • R’s vectorized operations don’t exist in JavaScript (operations apply to single values, not to entire arrays automatically)

Understanding these comparison and logical operators is fundamental to controlling the flow of your JavaScript programs and writing robust conditions for your applications.