Logical assignment operators in JavaScript: small syntax, big wins

2 min read
0 views

In day-to-day JavaScript, we often write code that checks a variable before assigning it a new value. These checks can get repetitive, especially when working with component props, global configs, or state objects. That’s where logical assignment operators come in, a compact ES2021 feature that simplifies common conditional assignments without changing the underlying logic.

What are logical assignment operators?

Logical assignment operators combine a logical operator (||, &&, or ??) with assignment (=) to create a shorthand form. These operators also short-circuit like regular logical expressions, meaning the right-hand side is only evaluated if the left-hand side fails the logical test (i.e., is falsy, truthy, or nullish).

⚠️ Note: Optional chaining (?.) isn’t allowed on the left-hand side of a logical assignment. It throws a syntax error:

// ❌ SyntaxError:
user?.settings ||= {};

Optional chaining returns the result of a property access, not a reference to the property itself. Since assignment targets must be references (i.e., a variable or object property), this isn’t valid JavaScript.

Logical OR assignment (||=)

Assign if falsy:

user.theme ||= 'light';

Equivalent to:

if (!user.theme) {
  user.theme = 'light';
}

This is useful for setting a default if a value hasn’t been initialized. But it overwrites values like 0, '', or false, which might be intentionally set.

Logical AND assignment (&&=)

Assign if truthy:

user.isLoggedIn &&= checkPermissions(user);

Equivalent to:

if (user.isLoggedIn) {
  user.isLoggedIn = checkPermissions(user);
}

This is helpful for conditionally updating a value based on an existing truthy value.

⚠️ Note: With &&=, the right-hand side is only evaluated if the left-hand side is truthy, and its actual result is assigned, even if that result is falsy.

let isEnabled = true;
isEnabled &&= false;
console.log(isEnabled); // false

The original value (true) acts as a gate, but it’s the result of checkPermissions (or any right-hand expression) that becomes the new value. &&= doesn’t preserve the old value, it replaces it.

Nullish coalescing assignment (??=)

Assign if nullish (null or undefined):

settings.timeout ??= 3000;

Equivalent to:

if (settings.timeout === null || settings.timeout === undefined) {
  settings.timeout = 3000;
}

Use this when you want to assign defaults only if the value is truly missing, not just falsy. Unlike ||=, it preserves valid values like 0, false, and ''.

Why logical assignment matters in your code

These operators aren’t just syntactic sugar. They solve real-world problems more safely and readably, especially when dealing with mutable state:

Defaulting component props

props.showHelpText ??= true;

Avoiding overwrites in global state or config

config.apiBase ||= '/api/v1';

Preventing accidental null/undefined assignments

formData.username &&= formData.username.trim();

But keep in mind

  • ||= assigns when the left-hand side is falsy, which includes 0, '', and false, values you might want to keep.

    let count = 0;
    count ||= 10; // overwrites count with 10, be careful!
    
  • Use ??= when you want to guard specifically against null or undefined, and preserve valid falsy values.
  • Right-hand expressions are only evaluated if needed, preserving performance and avoiding side effects.

    config.apiKey ||= fetchApiKey(); // fetchApiKey() only runs if apiKey is falsy
    

Example with a side effect

let calls = 0;
let obj = { val: 0 };

obj.val ||= ++calls;
console.log(obj.val); // 1, because 0 is falsy

obj.val ||= ++calls;
console.log(obj.val); // still 1, second increment never runs

Since obj.val is initially 0 (falsy), ++calls is evaluated and assigned. On the second line, obj.val is now 1 (truthy), so ++calls is skipped. The value of calls remains 1.

Browser support

Logical assignment operators are supported in all modern environments:

  • ✅ Chrome 85+, Firefox 79+, Safari 14+, Edge 85+
  • ✅ Node.js 15+
  • ❌ Not supported in Internet Explorer

If you’re targeting older environments, use a transpiler like @babel/preset-env with ES2021 settings.

Now you’re ready!

Logical assignment operators are a small but powerful addition to JavaScript. They clarify your semantic intent, reduce boilerplate, and simplify common conditional logic. They’re especially helpful in front-end workflows like:

  • Prop and state management
  • API defaults
  • Form sanitization

If you’re already comfortable using ||, &&, and ??, you’re ready for ||=, &&=, and ??=. It’s just muscle memory from here.