Operators, Comparisons, Conditionals, and Loops
This chapter covers the tools that control the flow of your JavaScript programs.
Basic Operators, Maths
Arithmetic Operators
let a = 10;
let b = 3;
a + b; // β 13 (addition)
a - b; // β 7 (subtraction)
a * b; // β 30 (multiplication)
a / b; // β 3.333... (division)
a % b; // β 1 (modulus / remainder)
a ** b; // β 1000 (exponentiation, ES2016)
String Concatenation with +
If any operand is a string, + becomes concatenation:
"Hello" + " " + "World"; // β "Hello World"
"3" + 4; // β "34"
3 + 4 + "5"; // β "75" (left to right: 3+4=7, 7+"5"="75")
Numeric Conversion with Unary +
+"42"; // β 42
+true; // β 1
+false; // β 0
+""; // β 0
Assignment Operators
let x = 5;
x += 3; // x = x + 3 β 8
x -= 2; // x = x - 2 β 6
x *= 4; // x = x * 4 β 24
x /= 3; // x = x / 3 β 8
x %= 5; // x = x % 5 β 3
x **= 2; // x = x ** 2 β 9
Increment / Decrement
let count = 0;
count++; // Post-increment: returns 0, then count becomes 1
++count; // Pre-increment: count becomes 2, returns 2
count--; // Post-decrement: returns 2, then count becomes 1
--count; // Pre-decrement: count becomes 0, returns 0
Operator Precedence
Some operators have higher priority than others, just like math:
(2 + 3) * 4; // β 20 (parentheses first)
2 + 3 * 4; // β 14 (multiplication before addition)
let a = 10, b = 3;
document.write('a = ' + a + ', b = ' + b + '<br>');
document.write('a + b = ' + (a + b) + '<br>');
document.write('a - b = ' + (a - b) + '<br>');
document.write('a * b = ' + (a * b) + '<br>');
document.write('a / b = ' + (a / b) + '<br>');
document.write('a % b = ' + (a % b) + '<br>');
document.write('a ** b = ' + (a ** b) + '<br>'); Comparisons
Comparisons return a boolean (true or false):
5 > 3; // β true
5 < 3; // β false
5 >= 5; // β true
5 <= 4; // β false
String Comparison
Strings are compared letter-by-letter lexicographically (dictionary order):
"a" < "b"; // β true
"Z" < "a"; // β true (uppercase have lower Unicode values)
"2" > "10"; // β true (compares "2" vs "1" β character by character!)
Different Types
When comparing different types, JavaScript converts them to numbers:
"2" > 1; // β true (string "2" becomes number 2)
"01" == 1; // β true ("01" becomes 1)
true == 1; // β true
false == 0; // β true
Strict Equality === vs Loose Equality ==
This is critical to understand:
// Loose == β converts types before comparing
5 == "5"; // β true
0 == false; // β true
null == undefined; // β true
// Strict === β no type conversion (check value AND type)
5 === "5"; // β false
0 === false; // β false
null === undefined; // β false
Always use
===and!==unless you have a specific reason to use==.
null and undefined comparisons
null == undefined; // β true (special rule)
null === undefined; // β false
// Comparisons with null/undefined can be tricky:
null > 0; // β false
null == 0; // β false
null >= 0; // β true (null converts to 0 for >=)
Conditional Branching: if, β?β
if Statement
let age = 18;
if (age >= 18) {
console.log("You can vote");
} else if (age >= 16) {
console.log("You can drive");
} else {
console.log("Too young");
}
Ternary Operator ?
Short form for simple conditionals:
let access = age >= 18 ? "Allowed" : "Denied";
// Same as:
// let access;
// if (age >= 18) access = "Allowed";
// else access = "Denied";
Nested ternaries (use sparingly β hard to read):
let category = age >= 18 ? "Adult" : age >= 13 ? "Teen" : "Child";
Truthy and Falsy in Conditionals
Values that evaluate to false in conditions:
if (0) {} // false
if ("") {} // false
if (null) {} // false
if (undefined) {} // false
if (NaN) {} // false
if (false) {} // false
Everything else is truthy β including "0", "false", empty arrays [], and empty objects {}.
Logical Operators
|| (OR)
Returns the first truthy value, or the last if all are falsy:
true || false; // β true
false || false; // β false
0 || 1 || 2; // β 1 (first truthy)
null || undefined || 0; // β 0 (all falsy β returns last)
// Practical: default value
let name = userInput || "Guest";
&& (AND)
Returns the first falsy value, or the last if all are truthy:
true && false; // β false
1 && 2 && 3; // β 3 (all truthy β returns last)
1 && 0 && 2; // β 0 (first falsy)
null && "hello"; // β null
// Practical: guard check
user && user.name; // β user.name if user exists, else null
! (NOT)
Returns the inverse boolean:
!true; // β false
!0; // β true
!!"hello"; // β true (double NOT β converts to boolean)
Short-circuit Evaluation
&& and || donβt evaluate the second operand if the first is sufficient:
false && console.log("Never runs"); // Short-circuits
true || console.log("Never runs"); // Short-circuits
let age = 22;
let hasLicense = true;
if (age >= 18 && hasLicense) {
document.write('You can drive!');
} else {
document.write('You cannot drive.');
}
document.write('<br>');
let user = null;
let displayName = user || 'Guest';
document.write('Welcome, ' + displayName); Nullish Coalescing Operator ??
Returns the right side only if the left is null or undefined:
let name = null;
let display = name ?? "Anonymous"; // β "Anonymous"
let age = 0;
let displayAge = age ?? 25; // β 0 (because 0 is neither null nor undefined)
Compare with ||:
let count = 0;
count || 10; // β 10 (0 is falsy)
count ?? 10; // β 0 (0 is not nullish)
Use
??for default values when0or""are valid values. Use||when you want to catch all falsy values.
?? cannot be combined with || or && without parentheses:
let x = 1 && 2 ?? 3; // SyntaxError!
let y = (1 && 2) ?? 3; // β 2 (OK with parentheses)
Loops: while and for
while Loop
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
// β 0, 1, 2, 3, 4
doβ¦while Loop
Always executes at least once:
let i = 0;
do {
console.log(i);
i++;
} while (i < 3);
// β 0, 1, 2
for Loop
for (let i = 0; i < 5; i++) {
console.log(i);
}
// β 0, 1, 2, 3, 4
Parts of the for loop:
for (initialization; condition; step) {
// body
}
Any part can be skipped:
let i = 0;
for (; i < 3; ) { // initialization and step are outside
console.log(i++);
}
Breaking the Loop
// break β exits the loop entirely
for (let i = 0; i < 10; i++) {
if (i === 3) break;
console.log(i);
}
// β 0, 1, 2
// continue β skips to the next iteration
for (let i = 0; i < 5; i++) {
if (i === 2) continue;
console.log(i);
}
// β 0, 1, 3, 4
Labels for Nested Loops
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) break outer;
console.log(`(${i},${j})`);
}
}
// β (0,0), (0,1), (0,2), (1,0)
document.write('<h3>Counting to 5:</h3>');
for (let i = 1; i <= 5; i++) {
document.write(i + ' ');
}
document.write('<h3>Even numbers:</h3>');
let n = 0;
while (n <= 10) {
if (n % 2 === 0) document.write(n + ' ');
n++;
}
document.write('<h3>Multiplication table (3):</h3>');
for (let i = 1; i <= 10; i++) {
document.write('3 Γ ' + i + ' = ' + (3 * i) + '<br>');
} The βswitchβ Statement
A cleaner alternative to multiple if...else if chains:
let day = 3;
let dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
default:
dayName = "Weekend";
}
console.log(dayName); // β "Wednesday"
How it works
switchcompares using strict equality (===)- The
breakis essential β without it, execution falls through to the next case:
let fruit = "apple";
switch (fruit) {
case "apple":
case "pear":
console.log("Common fruit");
break;
case "mango":
console.log("Tropical");
break;
}
// β "Common fruit" (because apple and pear share the same block)
Grouping cases
let grade = "B";
switch (grade) {
case "A":
case "B":
console.log("Great job!");
break;
case "C":
console.log("Good");
break;
case "D":
case "F":
console.log("Needs improvement");
break;
default:
console.log("Invalid grade");
}
let day = new Date().getDay();
let dayName;
switch (day) {
case 0: dayName = 'Sunday'; break;
case 1: dayName = 'Monday'; break;
case 2: dayName = 'Tuesday'; break;
case 3: dayName = 'Wednesday'; break;
case 4: dayName = 'Thursday'; break;
case 5: dayName = 'Friday'; break;
case 6: dayName = 'Saturday'; break;
default: dayName = 'Unknown';
}
document.write('Today is ' + dayName);