03. Operators and Expressions
Beyond the four basic operators you also have remainder `%`, exponentiation `**`, and increment/decrement `++`/`--`. Compound assignment operators like `+=`, `-=` are short and very common.
What you'll learn
- 1Use arithmetic, assignment, comparison, and logical operators appropriately.
- 2Understand the difference between `==` and `===` and default to `===`.
- 3Use short-circuit evaluation and nullish coalescing (`??`).
- 4Use optional chaining (`?.`) to access properties safely.
- 5Explain the difference between an expression and a statement.
Overview
Beyond the four basic operators you also have remainder `%`, exponentiation `**`, and increment/decrement `++`/`--`. Compound assignment operators like `+=`, `-=` are short and very common.
Core Concepts
1. Arithmetic and assignment
Beyond the four basic operators you also have remainder `%`, exponentiation `**`, and increment/decrement `++`/`--`. Compound assignment operators like `+=`, `-=` are short and very common.
let n = 10;
n **= 2; // 100
n %= 7; // 100 % 7 = 22. Comparison operators
`==` converts types before comparing; `===` checks both value and type. Use `===` in almost every case.
0 == ""; // true
0 === ""; // false
NaN === NaN; // false β use Number.isNaN3. Logical operators and short-circuit
`&&` and `||` don't return booleans β they return one of the original operands. `??` only falls through to the right when the left is `null` or `undefined`.
const name = userName || "anonymous"; // fallback when userName is falsy
const port = process.env.PORT ?? 3000; // fallback only on null/undefined4. Optional chaining
`?.` stops evaluating as soon as the left side is `null` or `undefined`, returning `undefined`. Great for digging into deeply nested objects safely.
const city = user?.address?.city ?? "unknown";
fn?.(); // call fn only if it exists
arr?.[0]; // first element only if arr existsExamples
| File | What it covers |
|---|---|
| `01_arithmetic.js` | Arithmetic and assignment, exponentiation, remainder |
| `02_comparison.js` | `==` vs `===` and comparing NaN |
| `03_logical.js` | `&&`, `||`, `??` |
| `04_optional_chaining.js` | Safe property access with `?.` |
src/01_arithmetic.js
/** Walk through arithmetic and compound-assignment operators. */
const a = 17;
const b = 5;
console.log("a + b =", a + b);
console.log("a - b =", a - b);
console.log("a * b =", a * b);
console.log("a / b =", a / b);
console.log("a % b =", a % b);
console.log("a ** b =", a ** b);
let n = 10;
n += 5; console.log("n += 5 β", n);
n *= 2; console.log("n *= 2 β", n);
n **= 2; console.log("n **= 2 β", n);
src/02_comparison.js
/** Show the difference between == and === and how NaN compares. */
console.log(0 == ""); // true
console.log(0 === ""); // false
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true
console.log(Object.is(NaN, NaN)); // true
src/03_logical.js
/** Compare the short-circuit behavior of &&, ||, and ??. */
const empty = "";
const zero = 0;
console.log(empty || "fallback"); // "fallback" (empty is falsy)
console.log(empty ?? "fallback"); // "" (not null/undefined)
console.log(zero || 100); // 100
console.log(zero ?? 100); // 0
// && returns the first falsy operand, or the last value
console.log(true && "ok"); // "ok"
console.log(0 && "skip"); // 0
src/04_optional_chaining.js
/** Optional chaining for safe property access. */
const user = {
name: "Ada",
address: { city: "London" },
};
console.log(user?.address?.city); // "London"
console.log(user?.company?.name); // undefined
console.log(user?.company?.name ?? "unemployed"); // "unemployed"
const maybeFn = undefined;
console.log(maybeFn?.()); // undefined (no error)
const arr = null;
console.log(arr?.[0]); // undefined
Common Mistakes
- Reaching for `||` in the `0 || default` pattern when you actually want `??` (because `0` should be a valid value).
- Assuming floating-point arithmetic is exact (`0.1 + 0.2 !== 0.3`).
- Forgetting that `NaN === NaN` is false and trying to compare with `=== NaN`.
- Subtle bugs caused by the difference between `++x` and `x++`.
- Making only the first step optional in `a?.b.c` and leaving the rest unguarded.
FAQ
Q1. Should I never use `==`?
The idiom `x == null` (catches both null and undefined) is fine, but otherwise stick to `===`.
Q2. Which should be my default, `??` or `||`?
If you mean "fall back when the value is missing", `??` is safer because it treats `0` and `""` as valid values.
Q3. What's the difference between an expression and a statement?
An expression evaluates to a value. A statement performs an action. `if (...)` is a statement; `a ? b : c` is an expression.
Practice
- `homework_01.js` β Print the sum, difference, quotient, remainder, and power of two numbers in a table.
- `homework_02.js` β Pull a safe value out of a nested object with `?.` and `??`.
homework/README.md
## homework_01.js
- Define two numbers `a` and `b` as constants and print +, -, *, /, %, ** via `console.table`.
## homework_02.js
- Use optional chaining to safely read `order.customer.address.city`.
- Fall back to "No address provided" when it's missing.
- Test with objects that are missing some of those properties.
homework/answer/homework_01.js
/** Print the arithmetic results of two numbers as a table. */
const a = 13;
const b = 4;
const result = {
"+": a + b,
"-": a - b,
"*": a * b,
"/": a / b,
"%": a % b,
"**": a ** b,
};
console.table(result);
homework/answer/homework_02.js
/** Safe lookup with optional chaining + nullish coalescing. */
const orders = [
{ id: 1, customer: { name: "A", address: { city: "Seoul" } } },
{ id: 2, customer: { name: "B" } },
{ id: 3 },
];
for (const order of orders) {
const city = order?.customer?.address?.city ?? "No address provided";
console.log(`Order ${order.id}: ${city}`);
}
Next Lecture
[04_Control_Flow](../04_μ μ΄λ¬Έ/) β Direct your program's flow with conditions and loops.
All lecture materials and example code are openly available on GitHub.
View on GitHub β