Episode 1 — Fundamentals / 1.18 — Operators and Type System

1.18.d — Assignment Operators

In one sentence: Assignment operators store values in variables — from the simple = to compound shortcuts like += and the modern logical assignment operators (&&=, ||=, ??=) that combine condition-checking with assignment in a single expression.

Navigation: ← 1.18.c — Logical Operators · 1.18.e — typeof Operator →


1. Basic assignment =

The = operator assigns the right-hand side value to the left-hand side variable.

let x = 10;
const name = "Alice";
let arr = [1, 2, 3];

Assignment is an expression (it returns a value)

let a;
let b;
console.log(a = 5);   // 5  (the assignment expression evaluates to 5)

This is why assignments can be used inside conditions (though you usually should not):

let line;
// Reading lines — assignment inside while condition (rare but valid pattern)
// while ((line = readline()) !== null) { ... }

2. Compound assignment operators

Compound operators combine an arithmetic/bitwise operation with assignment. x op= y is shorthand for x = x op y.

OperatorEquivalent toExample
+=x = x + valuecount += 1
-=x = x - valuebalance -= withdrawal
*=x = x * valueprice *= taxRate
/=x = x / valuetotal /= numPeople
%=x = x % valueindex %= length
**=x = x ** valuebase **= exponent
let score = 100;
score += 10;    // 110
score -= 25;    // 85
score *= 2;     // 170
score /= 10;    // 17
score %= 5;     // 2
score **= 3;    // 8

console.log(score);  // 8

String concatenation with +=

let message = "Hello";
message += " ";
message += "World";
console.log(message);  // "Hello World"

// Building output in a loop
let output = "";
for (let i = 1; i <= 5; i++) {
  output += `Item ${i}\n`;
}
console.log(output);
// Item 1
// Item 2
// Item 3
// Item 4
// Item 5

3. Practical usage patterns

Accumulator in a loop

const prices = [29.99, 9.99, 49.99, 14.99];
let total = 0;
for (const price of prices) {
  total += price;
}
console.log(total.toFixed(2));  // "104.96"

Counter

let errorCount = 0;
const logs = ["INFO: ok", "ERROR: fail", "INFO: ok", "ERROR: timeout"];
for (const log of logs) {
  if (log.startsWith("ERROR")) {
    errorCount += 1;  // or errorCount++
  }
}
console.log(errorCount);  // 2

Percentage scaling

let price = 100;
// Apply 20% discount
price *= 0.80;
console.log(price);  // 80

// Apply 10% tax
price *= 1.10;
console.log(price);  // 88

Wrapping index

let index = 0;
const items = ["a", "b", "c"];

function next() {
  const item = items[index];
  index = (index + 1) % items.length;
  // Or: index += 1; index %= items.length;
  return item;
}

console.log(next());  // "a"
console.log(next());  // "b"
console.log(next());  // "c"
console.log(next());  // "a" (wraps around)

4. Logical assignment operators (ES2021)

These three operators combine a logical check with assignment. They only assign if the condition is met.

||= — assign if left is falsy

// x ||= y  means:  x || (x = y)
// Only assigns if x is currently falsy

let username = "";
username ||= "Guest";
console.log(username);  // "Guest" (empty string is falsy)

let count = 0;
count ||= 10;
console.log(count);  // 10 (0 is falsy — this may be a bug!)

let name = "Alice";
name ||= "Guest";
console.log(name);  // "Alice" (truthy — no assignment)

&&= — assign if left is truthy

// x &&= y  means:  x && (x = y)
// Only assigns if x is currently truthy

let config = { debug: true };
config.debug &&= false;       // debug was truthy → now false
console.log(config.debug);    // false

let setting = null;
setting &&= "new value";      // null is falsy → no assignment
console.log(setting);         // null

Use case: Transform a value only if it exists.

let userInput = "  hello  ";
userInput &&= userInput.trim();
console.log(userInput);  // "hello"

let empty = "";
empty &&= empty.trim();
console.log(empty);  // "" (falsy — no assignment, stays "")

??= — assign if left is null or undefined

// x ??= y  means:  x ?? (x = y)
// Only assigns if x is null or undefined

let volume = 0;
volume ??= 50;
console.log(volume);  // 0 (0 is NOT null/undefined — no assignment)

let theme = null;
theme ??= "light";
console.log(theme);  // "light"

let port = undefined;
port ??= 3000;
console.log(port);  // 3000

Comparison table

OperatorAssigns when left is...Preserves 0?Preserves ""?Preserves false?
||=FalsyNoNoNo
&&=Truthyn/an/an/a
??=null or undefinedYesYesYes

Real-world: initializing defaults in objects

const options = {
  timeout: undefined,
  retries: 0,
  verbose: false,
};

// Safe defaults that preserve 0 and false
options.timeout ??= 5000;
options.retries ??= 3;
options.verbose ??= true;

console.log(options);
// { timeout: 5000, retries: 0, verbose: false }
// retries stayed 0, verbose stayed false — correct!

Real-world: lazy initialization

class Cache {
  #store = {};

  get(key, computeFn) {
    // Only compute if not already cached
    this.#store[key] ??= computeFn();
    return this.#store[key];
  }
}

const cache = new Cache();
cache.get("data", () => expensiveOperation());  // computes
cache.get("data", () => expensiveOperation());  // returns cached

5. Destructuring assignment (preview)

Destructuring lets you unpack values from arrays or objects into variables. Full coverage is in the Arrays and Objects sections — here is a brief preview since it uses =.

Array destructuring

const [first, second, third] = [10, 20, 30];
console.log(first);   // 10
console.log(second);  // 20
console.log(third);   // 30

// Skip values
const [a, , c] = [1, 2, 3];
console.log(a);  // 1
console.log(c);  // 3

// Swap variables (no temp needed!)
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x);  // 2
console.log(y);  // 1

Object destructuring

const user = { name: "Alice", age: 30, role: "admin" };
const { name, age } = user;
console.log(name);  // "Alice"
console.log(age);   // 30

// With renaming
const { name: userName, role: userRole } = user;
console.log(userName);  // "Alice"
console.log(userRole);  // "admin"

// With defaults
const { theme = "light" } = {};
console.log(theme);  // "light"

6. Chained assignment and why to avoid it

JavaScript allows chaining assignments because = returns the assigned value:

let a, b, c;
a = b = c = 10;
console.log(a, b, c);  // 10 10 10

Why you should avoid it

// Problem 1: accidental global
let x = y = 5;
// This is: y = 5 (y is NOT declared with let — it becomes a global!)
//          let x = y;

// Problem 2: readability
a = b = c = d = computeValue();  // Which variable matters? Hard to debug.

// Better: explicit declarations
const value = computeValue();
let a = value;
let b = value;
let c = value;

ESLint: The no-multi-assign rule flags chained assignment.


7. Common mistakes

Confusing = with ===

let status = "active";

// BUG: assigns "inactive" instead of comparing
if (status = "inactive") {
  console.log("This always runs!");  // "inactive" is truthy
}

// CORRECT
if (status === "inactive") {
  console.log("Deactivated");
}

Using ||= when ??= is intended

let retries = 0;

// BUG: 0 is falsy, so this overwrites a valid value
retries ||= 3;
console.log(retries);  // 3 (wrong — user set 0 retries)

// CORRECT
retries = 0;
retries ??= 3;
console.log(retries);  // 0 (correct)

Forgetting let/const with compound assignment

// ReferenceError: total is not defined
// total += 5;  // Cannot compound-assign to an undeclared variable

let total = 0;
total += 5;     // Works: 5

Key takeaways

  1. = assigns and returns the value — but avoid using it inside expressions for clarity.
  2. Compound operators (+=, -=, *=, /=, %=, **=) are shorthand for operate-then-assign.
  3. ||= assigns if the current value is falsy — beware of 0, "", false.
  4. &&= assigns if the current value is truthy — useful for transforming existing values.
  5. ??= assigns only if the current value is null or undefined — the safest default-assignment operator.
  6. Chained assignment (a = b = c = 5) can create accidental globals and hurts readability.
  7. Destructuring is a special form of assignment for unpacking arrays and objects.

Explain-It Challenge

Explain without notes:

  1. What is the difference between x ||= 5 and x ??= 5 when x is 0?
  2. Why is chained assignment like let x = y = 10 potentially dangerous?
  3. Show how += can be used with both numbers and strings.
  4. What does &&= do, and give a practical use case?
  5. Write code that initializes options.timeout to 3000 only if it is null or undefined, using a logical assignment operator.

Navigation: ← 1.18.c — Logical Operators · 1.18.e — typeof Operator →