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.
| Operator | Equivalent to | Example |
|---|---|---|
+= | x = x + value | count += 1 |
-= | x = x - value | balance -= withdrawal |
*= | x = x * value | price *= taxRate |
/= | x = x / value | total /= numPeople |
%= | x = x % value | index %= length |
**= | x = x ** value | base **= 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
| Operator | Assigns when left is... | Preserves 0? | Preserves ""? | Preserves false? |
|---|---|---|---|---|
||= | Falsy | No | No | No |
&&= | Truthy | n/a | n/a | n/a |
??= | null or undefined | Yes | Yes | Yes |
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
=assigns and returns the value — but avoid using it inside expressions for clarity.- Compound operators (
+=,-=,*=,/=,%=,**=) are shorthand for operate-then-assign. ||=assigns if the current value is falsy — beware of0,"",false.&&=assigns if the current value is truthy — useful for transforming existing values.??=assigns only if the current value isnullorundefined— the safest default-assignment operator.- Chained assignment (
a = b = c = 5) can create accidental globals and hurts readability. - Destructuring is a special form of assignment for unpacking arrays and objects.
Explain-It Challenge
Explain without notes:
- What is the difference between
x ||= 5andx ??= 5whenxis0? - Why is chained assignment like
let x = y = 10potentially dangerous? - Show how
+=can be used with both numbers and strings. - What does
&&=do, and give a practical use case? - Write code that initializes
options.timeoutto3000only if it isnullorundefined, using a logical assignment operator.
Navigation: ← 1.18.c — Logical Operators · 1.18.e — typeof Operator →