Last 30 Days
No notifications
JavaScript's operators look familiar — but a few of them have famous quirks (== vs ===, + on strings, the new nullish ??). This page puts them all in one place: arithmetic, comparison, logical, plus the modern essentials — optional chaining ?., nullish coalescing ??, and template literals.
# Operators & Type Coercion
1 + 2 // 3
10 / 3 // 3.333... (no integer division)
10 % 3 // 1 (remainder)
2 ** 10 // 1024 (power)
-5 // unary minuslet n = 5;
n++; // post-increment: returns 5, then n becomes 6
++n; // pre-increment: n becomes 7, returns 7
+ operator — string OR number+ is overloaded. If either side is a string, both sides become strings.
1 + 2 // 3
"1" + 2 // "12" ← coercion to string
1 + "2" // "12"
"5" - 2 // 3 ← only + does string concat; -, *, / coerce to numbers
"5" * "3" // 15===| op | name | does coercion? |
== | loose equal | yes (the famous WAT cases) |
=== | strict equal | no — types must match |
!= | loose != | yes |
!== | strict != | no |
0 == false // true (coerced)
"" == 0 // true
null == undefined // true (the only useful loose-equal case)
0 === false // false
"" === 0 // false
NaN === NaN // false (always)
> Rule: use === and !== everywhere. ESLint will yell at you if you don't.&& returns the first falsy operand (or the last if all truthy).
|| returns the first truthy operand (or the last if all falsy).true && "ok" // "ok"
false && "ok" // false
0 && "ok" // 0
"a" || "b" // "a"
"" "b" // "b"const name = userName
"anonymous"; // classic default fallback|| but only falls back on null/undefined — NOT on 0, "", false.
0 || 100 // 100 (often a bug — 0 is a real value)
0 ?? 100 // 0 (correct — only null/undefined trigger fallback)
"" ?? "default" // ""
null ?? "default" // "default"null/undefined instead of throwing.
const user = { profile: null };user.profile.name // ❌ TypeError
user.profile?.name // ✅ undefined
user.profile?.name ?? "guest" // ✅ "guest"
arr?.[0]?.toUpperCase() // works for arrays + functions too
fn?.(args) // calls fn only if it exists
cond ? a : bconst status = score >= 60 ? "pass" : "fail";
Don't nest more than one level — switch to if/else for readability.const name = "alice";
const greeting = hello ${name}, today is ${new Date().toDateString()};
const html = `
<div>
<h1>${name}</h1>
</div>
`;... and rest ...// SPREAD — expand into individual elements
const a = [1, 2, 3];
const b = [...a, 4, 5]; // [1, 2, 3, 4, 5]
const c = { ...user, age: 22 }; // shallow merge// REST — collect remaining args into an array
function sum(...nums) {
return nums.reduce((s, n) => s + n, 0);
}
sum(1, 2, 3, 4); // 10
5 & 3 // 1
5 | 3 // 7
5 ^ 3 // 6 XOR — neat for swap without temp
5 << 1 // 10
5 >> 1 // 2
~5 // -6 NOT