JavaScript Conditions
Master control flow, boolean type coercion, switch fallthrough mechanics, expressions vs statements, and clean architectural guard clauses.
1. Control Flow & Boolean Coercion Mechanics
By default, JavaScript executes code sequentially from top to bottom. Conditional statements alter this linear execution by creating decision branches based on dynamic boolean expressions.
When an expression is passed into a condition like if (expression), the JavaScript engine performs an internal abstract operation called ToBoolean(argument) to coerce the value into either true or false.
The 8 Falsy Values in JavaScript ❌
In the entire JavaScript language, only these 8 values evaluate to false:
false(boolean literal)0,-0,0n(BigInt zero)""(empty string with zero length)null(intentional absence of value)undefined(uninitialized variable)NaN(Not-a-Number from invalid math)
Truthy Values (Everything Else! ✅)
All other values evaluate to true in boolean context, including:
"0"&"false"(any non-empty string is truthy)[](empty array — exists in memory!){}(empty object — exists in memory!)function() {}(callable function object)- Any non-zero numbers (e.g.,
-10,3.14)
💡 Why are [] and {} Truthy?
In JavaScript, arrays and objects are Reference Types stored in heap memory. Even if an array has 0 elements ([].length === 0), the variable holds a valid memory reference address. In boolean conversion, any valid object reference always evaluates to true! To verify an empty array, always check its length: if (arr.length > 0).
// Demonstrating Boolean Coercion:
console.log(Boolean([])); // true (Valid heap reference)
console.log(Boolean({})); // true (Valid heap reference)
console.log(Boolean("")); // false (Empty primitive string)
console.log(Boolean("0")); // true (Non-empty string)
console.log(Boolean(0)); // false (Numeric zero)
true true false true false
2. The if, else if, and else Decision Ladder
The if-else ladder evaluates conditions sequentially from top to bottom. As soon as a branch condition evaluates to true, its code block executes, and the engine immediately skips all subsequent branches without evaluating them.
const studentScore = 85;
if (studentScore >= 90) {
console.log("Grade: A+ (Honors)");
} else if (studentScore >= 80) {
console.log("Grade: A (First Class)"); // Matches here -> Skips rest!
} else if (studentScore >= 70) {
console.log("Grade: B");
} else {
console.log("Grade: Needs Improvement");
}
Grade: A (First Class)
3. The switch Statement & Fallthrough Mechanics
When you need to match a single variable against multiple discrete constant values (e.g., user roles, HTTP status codes, actions), a switch statement is often cleaner than a long chain of if-else checks.
Core Rules of switch:
- Strict Comparison:
switchcompares expressions using strict equality (===). It will not perform automatic type conversions (e.g.,"200"will not match200). - Fallthrough Mechanics: Once a matching
caseis found, execution continues into subsequent cases sequentially until it encounters abreakstatement or the block ends.
const userRole = "admin";
switch (userRole) {
case "admin":
console.log("Permissions: Full Read, Write & Delete");
break; // Prevents fallthrough into editor!
case "editor":
console.log("Permissions: Read & Write");
break;
case "viewer":
console.log("Permissions: Read Only");
break;
default:
console.log("Permissions: Access Denied");
}
// Intentional Fallthrough Grouping (Shared logic for multiple cases):
const currentDay = "Sunday";
switch (currentDay) {
case "Saturday":
case "Sunday":
console.log("Schedule: Weekend Off! 🎉");
break;
default:
console.log("Schedule: Workday 💻");
}
Permissions: Full Read, Write & Delete Schedule: Weekend Off! 🎉
4. The Ternary Operator: Expressions vs Statements
To understand the conditional operator (? :), you must understand the fundamental difference between an Expression and a Statement:
- Statement (e.g.,
if-else): Performs an action or instruction. It produces no value of its own, so you cannot directly assign it to a variable (e.g.,const x = if(a) { 1 }is a syntax error). - Expression (e.g.,
a ? b : c): Evaluates down to a concrete single value. It can be directly assigned to variables, passed into function parameters, or embedded in React JSX.
Clean: Single Binary Check ✅
Ideal for inline assignments and concise variable initialization.
const userAge = 20;
const permission = userAge >= 18 ? "Granted" : "Denied";
console.log(permission); // "Granted"
Anti-Pattern: Nested Ternaries ❌
Avoid chaining multiple ternaries. They hurt readability and maintainability.
const score = 85;
// Hard to read & debug:
const tag = score > 90 ? "A" : score > 80 ? "B" : "C";
5. Clean Architecture: The Guard Clause Pattern
In real-world software engineering, deeply nested if statements (often called the Pyramid of Doom or Arrow Anti-Pattern) dramatically increase Cyclomatic Complexity — making code harder to read, debug, and test.
The Solution: The Bouncer / Guard Clause Pattern:
Check for invalid conditions, missing data, and unauthorized access first, and return immediately. This keeps your core "happy path" logic flat, clean, and un-indented at the root level.
❌ Deeply Nested (Pyramid of Doom)
function placeOrder(user, cart) {
if (user) {
if (user.isLoggedIn) {
if (cart.length > 0) {
return "Order Placed!";
} else {
return "Cart is empty";
}
} else {
return "Please login";
}
} else {
return "No user found";
}
}
✅ Clean Guard Clauses (Flat & Fail-Fast)
function placeOrder(user, cart) {
// 1. Fail-fast error checks first
if (!user) return "No user found";
if (!user.isLoggedIn) return "Please login";
if (cart.length === 0) return "Cart is empty";
// 2. Main happy path sits clean & flat!
return "Order Placed!";
}
6. Conditions Interview Deck
Test your understanding of JavaScript conditional branches, truthy/falsy coercion, and switch fallthrough:
7. Practice Challenge
🎯 Coding Challenge: Clean Guard Clauses
Write a function validateUser(user) using Guard Clauses (early returns):
1. If !user, return "Error: User required".
2. If !user.isVerified, return "Error: Unverified".
3. If user.age < 18, return "Error: Underage".
4. Otherwise, return "Access granted to " + user.name.