Comparison & Logical Operators
Comparison operators ask questions — is this bigger, are these equal? — and answer with true or false. Logical operators combine those answers. Together they're the building blocks of every decision a program makes.
Comparison operators
const age = 20;
console.log(age > 18);
console.log(age < 18);
console.log(age >= 20);
console.log(age <= 19);
console.log(age === 20);
console.log(age !== 20);
true false true false true false
Strict (===) vs loose (==) equality
JavaScript has two equality operators. === is strict: values must have the same type and the same value. == is loose: it converts types first, with rules that are hard to remember:
console.log(5 === "5"); console.log(5 == "5"); console.log(0 == ""); console.log(0 == false); console.log(null == undefined); console.log(null === undefined);
false true true true true false
Always use === and !==. The only common exception is value == null, which is a deliberate shortcut for "null or undefined".
NaN is not equal to anything, including itself — NaN === NaN is false. Use Number.isNaN(value) to test for it.Comparing strings
Strings are compared character by character using their Unicode values, which is alphabetical for simple lowercase text — but uppercase letters come before all lowercase ones:
console.log("apple" < "banana"); console.log("Zebra" < "apple"); console.log("10" < "9"); console.log(10 < 9);
true true true false
"10" < "9" is true because the character "1" comes before "9". Make sure numbers are numbers before comparing them. For human-friendly sorting, use localeCompare (lesson 32).
Logical operators
| Operator | Name | True when… |
|---|---|---|
&& | AND | both sides are true |
|| | OR | at least one side is true |
! | NOT | flips true to false and back |
const hasTicket = true; const isVip = false; const age = 16; console.log(hasTicket && age >= 18); console.log(hasTicket || isVip); console.log(!isVip); console.log((hasTicket && age >= 18) || isVip);
false true true false
&& binds more tightly than ||, but parentheses make combined conditions much easier to read.
Short-circuiting
Logical operators stop as soon as the answer is known. && stops at the first falsy value; || stops at the first truthy one. They also return the value where they stopped — not necessarily true or false:
console.log("cat" && "dog"); console.log("" && "dog"); console.log("" || "default"); console.log("chosen" || "default"); const user = null; console.log(user && user.name);
dog default chosen null
The second line prints an empty string. user && user.name is a classic guard: if user is missing, the expression stops and never tries to read .name. "Truthy" and "falsy" are explained fully in lesson 19.
Nullish coalescing: ??
|| is often used for default values, but it treats 0, "" and false as missing. ?? only falls back when the left side is null or undefined:
const volume = 0; console.log(volume || 50); console.log(volume ?? 50); console.log(undefined ?? 50);
50 0 50
Use ?? for defaults whenever 0, "" or false are valid values.
Optional chaining: ?.
?. reads a property only if the thing before it exists, returning undefined instead of crashing:
const order = { customer: { name: "Kai" } }; const emptyOrder = {}; console.log(order.customer?.name); console.log(emptyOrder.customer?.name); console.log(emptyOrder.customer?.name ?? "Guest");
Kai undefined Guest
Logical assignment
const settings = { theme: "", retries: 0 }; settings.theme ||= "light"; settings.retries ??= 3; settings.language ??= "en"; console.log(settings);
{ theme: 'light', retries: 0, language: 'en' }a ||= b assigns only if a is falsy; a ??= b only if a is null/undefined; a &&= b only if a is truthy.