Introduction

Beyond basic &&, ||, and !, JavaScript offers powerful logical patterns for cleaner code. Short-circuit evaluation, nullish coalescing, and logical assignment operators can replace verbose if statements. Master these to write more expressive, concise JavaScript.

Key Concepts

Short-circuit Evaluation: Logical operators stop evaluating as soon as the result is determined.

Logical Assignment Operators (ES2021): Combine logical operators with assignment (&&=, ||=, ??=).

Truthy Evaluation: How values are evaluated in boolean contexts.

Real World Context

Setting default values, conditionally calling functions, updating state only when needed, providing fallbacks for missing data—logical operators handle these patterns elegantly without if statements.

Deep Dive

Short-circuit Evaluation

javascript
// AND short-circuits on first falsy
false && expensive();  // expensive() never called
const name = user && user.name;  // Safe property access

// OR short-circuits on first truthy
true || expensive();  // expensive() never called
const theme = userTheme || 'default';  // Fallback value

Logical Operators Return Values (Not Booleans!)

javascript
// && returns first falsy OR last value
'hello' && 'world';  // 'world'
'' && 'world';       // ''
0 && 'hello';        // 0

// || returns first truthy OR last value
'' || 'fallback';    // 'fallback'
'value' || 'fallback'; // 'value'
0 || null || 'last'; // 'last'

Nullish Coalescing (??)

javascript
// Only null/undefined trigger fallback
const a = null ?? 'default';     // 'default'
const b = undefined ?? 'default'; // 'default'
const c = 0 ?? 'default';        // 0 (not null/undefined)
const d = '' ?? 'default';       // '' (not null/undefined)
const e = false ?? 'default';    // false (not null/undefined)

// Compare with ||
const f = 0 || 'default';        // 'default' (0 is falsy)

Logical Assignment Operators (ES2021)

javascript
let a = null;
let b = 'existing';
let c = 0;

// ||= assigns if current value is falsy
a ||= 'default';  // a = 'default'
b ||= 'default';  // b = 'existing' (unchanged)
c ||= 5;          // c = 5 (0 is falsy)

// ??= assigns if current value is null/undefined
let d = null;
let e = 0;
d ??= 'default';  // d = 'default'
e ??= 5;          // e = 0 (unchanged, 0 is not nullish)

// &&= assigns if current value is truthy
let user = { name: 'Alice' };
user &&= { ...user, loggedIn: true };  // Adds property if user exists

Practical Patterns

javascript
// Default parameters alternative
function greet(name) {
  name ??= 'Guest';
  console.log(`Hello, ${name}!`);
}

// Conditional function call
const callback = options.onSuccess;
callback?.();  // Only calls if callback exists

// Object property defaults
const config = {};
config.timeout ??= 3000;
config.retries ??= 3;

Common Pitfalls

  1. Mixing ?? with && or || without parentheses: Causes syntax error.
  2. Using ||= when you want ??=: ||= treats 0 and '' as triggers for assignment.
  3. Forgetting that logical operators return values: Not necessarily booleans.

Best Practices

  • Use ?? for default values: When 0, '', or false are valid values.
  • Use ??= for initialization: Cleaner than if (x === null) x = default.
  • Use && for conditional execution: Instead of if (condition) fn().
  • Parenthesize mixed operators: (a ?? b) || c for clarity.

Summary

Logical operators (&&, ||) short-circuit and return values, not just booleans. Nullish coalescing (??) only triggers on null/undefined. Logical assignment operators (||=, &&=, ??=) combine logic with assignment for concise initialization patterns.

Code Examples

javascript
// AND short-circuits on first falsy
false && expensive();  // expensive() never called
const name = user && user.name;  // Safe property access

// OR short-circuits on first truthy
true || expensive();  // expensive() never called
const theme = userTheme || 'default';  // Fallback value
javascript
// && returns first falsy OR last value
'hello' && 'world';  // 'world'
'' && 'world';       // ''
0 && 'hello';        // 0

// || returns first truthy OR last value
'' || 'fallback';    // 'fallback'
'value' || 'fallback'; // 'value'
0 || null || 'last'; // 'last'
✓ Completed