Operators, Coercion and Numbers
== coerces, + prefers strings, and every number is a float. This lesson builds a precise model so the surprises become predictable.
Arithmetic — and the + trap
The arithmetic set
console.log(7 + 3, 7 - 3, 7 * 3); // 10 4 21
console.log(7 / 2); // 3.5 — division always allows decimals
console.log(7 % 2); // 1 — remainder: "is 7 odd?" is 7 % 2 === 1
console.log(2 ** 10); // 1024 — exponent (not ^ — that is bitwise XOR)
% (remainder) is more useful than it looks: cycles, "every 5th item", even/odd
checks.
The + operator decides: text or math
The + operator's decision, in full. One rule explains the whole "1" + 2 family of surprises.
console.log(1 + 2); // 3
console.log("1" + 2); // "12" — a string wins, everything joins as text
console.log(1 + 2 + "3"); // "33" — left to right: 1+2=3, then "3"+"3"
console.log("6" - 1); // 5 — - has no text meaning, so it converts!
The habit: never rely on these conversions. Convert explicitly with
Number("6") / String(6) and the behaviour is always yours.
Equality
Strict versus loose — run the lab
console.log("5" == 5); // true — == CONVERTS first, then compares
console.log("5" === 5); // false — === compares type AND value
console.log(0 == ""); // true — both convert to 0. A bug factory.
console.log(null == undefined); // true — one special-case pair
== has a page of conversion rules in the spec; === has one sentence.
The professional rule: use === and !== everywhere.
NaN — and how to test it
console.log(NaN === NaN); // false — NaN equals nothing, itself included
console.log(Number.isNaN(0 / 0)); // true — the ONLY correct NaN test
Truthiness
Every value is secretly true or false
Inside an if, any value converts to true or false. The
false team has exactly six members — memorise the list; everything else is truthy:
// falsy: 0, "" (empty string), null, undefined, NaN, false
console.log(Boolean(0), Boolean(""), Boolean("0")); // false false TRUE — "0" is text!
&& and || return values, not just answers
// && returns the first falsy side (or the last value if all truthy):
console.log(user && user.name); // if user is null, the expression stops there
// || returns the first truthy side — the classic "default value" trick:
const port = settings.port || 8080;
?? — defaulting that respects zero
const volume = 0;
console.log(volume || 50); // 50 — WRONG: 0 is falsy, so the fallback fired
console.log(volume ?? 50); // 0 — RIGHT: ?? only falls back on null/undefined
If you get this instead: a setting of 0 or ""
silently ignored — a || was used where ?? was meant. One character,
two different defaulting styles.
?. — read deep without crashing
const city = user?.address?.city; // undefined instead of a TypeError
// when user or address is null/undefined
?. short-circuits the whole chain to undefined when the left side is
nullish. It replaces pages of if (user && user.address && ...).
Numbers are floats
IEEE-754 in practice
console.log(0.1 + 0.2); // 0.30000000000000004 — not YOUR bug
console.log(0.1 + 0.2 === 0.3); // false
console.log((0.1 * 10 + 0.2 * 10) / 10); // 0.3 — the standard money fix
Every number is a 64-bit float; decimals are approximations. Never compare computed floats with
=== — round, or work in whole units (cents).
Parsing and converting
console.log(Number("12.5")); // 12.5 — strict: "" → 0, "abc" → NaN
console.log(parseInt("12px")); // 12 — reads what it can from the start
console.log(parseInt("08", 10)); // 8 — ALWAYS pass the radix 10
Number() for clean input, parseInt(s, 10) for leading-number strings,
Number.isNaN to check the result. BigInt (an n suffix:
10n) handles integers beyond Number.MAX_SAFE_INTEGER — rare on day
one, vital for IDs and finance.
Practice: the coercion lab
The task
Run foundations/10_coercion_lab.js with node. Before each output
appears, say the expected value out loud. Keep a personal "surprises" list — that list is your
actual curriculum.
The checklist
- You can explain the
+decision from the diagram without looking. - You can name all six falsy values.
- You know when
||betrays you and??does not. - You can explain why
0.1 + 0.2 !== 0.3and what to do about money.