New to Rust? Grab our free Rust for Beginners eBook Get it free →
JavaScript if else: Syntax, Examples and Best Practices

The JavaScript if else statement is how your code makes decisions. When a condition evaluates to true, one block runs. When it evaluates to false, another runs. It sounds simple, but getting the details right (truthy values, operator precedence, dangling else, when to reach for a ternary) separates readable code from brittle code. This article covers all of it, with the three classic examples that show the pattern in action.
The if statement
The if statement is the foundation. JavaScript evaluates the expression inside the parentheses, and if it’s truthy, the block executes.
if (condition) {
// runs when condition is truthy
}
A condition doesn’t have to be a strict boolean. JavaScript converts any value to boolean for the check. The falsy values are false, 0, -0, 0n, "", null, undefined and NaN. Everything else is truthy, including empty arrays and empty objects, which trips people up. So if ([]) executes. If you’re checking for an empty array you need if (arr.length > 0).
let score = 80;
if (score >= 60) {
console.log("Passed.");
}
// Output: Passed.
The if else statement
Add an else clause to handle the false branch. Exactly one of the two blocks runs.
if (condition) {
// runs when true
} else {
// runs when false
}
The flowchart is simple: one path for true, one for false, both converge afterward.

let age = 20;
if (age >= 18) {
console.log("Adult.");
} else {
console.log("Minor.");
}
// Output: Adult.
Always use curly braces, even for single-line branches. JavaScript allows you to omit them, but doing so invites the dangling else bug. Consider this:
function check(a, b) {
if (a === 1)
if (b === 2)
console.log("both match");
else
console.log("a is not 1"); // misleading indentation
}
That else binds to the inner if, not the outer one. The fix is always explicit blocks:
function check(a, b) {
if (a === 1) {
if (b === 2) {
console.log("both match");
}
} else {
console.log("a is not 1");
}
}
The else if ladder
When you have more than two branches, chain else if blocks. JavaScript evaluates them in order and executes the first one that matches, then skips the rest.
if (condition1) {
// first match
} else if (condition2) {
// second match
} else if (condition3) {
// third match
} else {
// none matched
}
There’s no elseif keyword in JavaScript. It’s always two words. What looks like one keyword is really else followed by a new if statement.
Examples
Example 1: check if a number is even or odd
The code below determines whether a number given by a user as input is either even or odd using the if else statement.
var x = prompt("Enter a Value", "0");
var num1 = parseInt(x);
if (num1%2 ==0)
{
document.write("number is even");
}
else
{
document.write("number is odd");
}
After running the above code, the user will be prompted to enter a number. In this case, entering 14 checks the if condition. The output is:
number is even

An odd number can also be given as input to confirm the else branch works.
Example 2: check the current time and report on it
This program obtains the present time and determines what part of the day it is:
var Time_today = new Date().getHours();
if (Time_today<10)
{
document.write("It is morning time.");
}
else if (Time_today<20) {
document.write("It is day time.");
}
else
{
document.write("It is evening/night time.");
}
The output depends on when you run it:
It is morning time

This is the else if ladder in practice: getHours() returns 0 to 23, and the two thresholds split the day into three named periods.
Example 3: check the sides of a triangle and determine its type
This example takes three sides as user input and determines whether the triangle is equilateral (all sides equal), isosceles (any two sides equal) or scalene (no sides equal):
var firstside=prompt("Enter 1st side of triangle");
var secondside=prompt("Enter 2nd side of triangle");
var thirdside=prompt("Enter 3rd side of triangle");
var num1 = parseInt(firstside);
var num2 = parseInt(secondside);
var num3 = parseInt(thirdside);
if ((num1 == num2) && (num1==num3))
{
document.write("It is an equilateral triangle.");
}
else if ((num1 == num2 ) || (num2==num3) || (num3==num1))
{
document.write("It is an isosceles triangle");
}
else
{
document.write("It is a scalene triangle.");
}
Entering sides 5, 6 and 7 gives:
It is a scalene triangle.

This example also shows && and || inside conditions, which is worth breaking down separately.
Logical operators inside conditions
You can combine multiple checks in a single if using JavaScript operators.
AND (&&): both sides must be truthy. Returns the first falsy value it hits, or the last value if all are truthy.
let age = 25;
let hasLicense = true;
if (age >= 18 && hasLicense) {
console.log("Can drive.");
}
// Output: Can drive.
OR (||): at least one side must be truthy. Returns the first truthy value it hits.
let isWeekend = false;
let isHoliday = true;
if (isWeekend || isHoliday) {
console.log("Day off.");
}
// Output: Day off.
NOT (!): inverts truthiness. Handy for guard clauses.
let isLoggedIn = false;
if (!isLoggedIn) {
console.log("Please sign in.");
}
// Output: Please sign in.
Short-circuit evaluation means JavaScript stops as soon as it knows the result. false && expensiveCall() never calls expensiveCall. true || expensiveCall() does the same on the OR side. This matters in performance-sensitive conditions.
Nested if else
You can put an if else block inside another if else block. This is useful when a second decision only makes sense once the first condition passes.
let marks = 72;
if (marks >= 40) {
if (marks >= 80) {
console.log("Distinction");
} else {
console.log("Passed");
}
} else {
console.log("Failed");
}
// Output: Passed
Use this sparingly. More than two levels of nesting is usually a sign the logic should be refactored, either pulled into a function or rewritten as a flat else if ladder.
Ternary operator: if…else on one line
For a simple two-branch assignment, the JavaScript ternary operator ?: is cleaner than a full if else block.
let result = condition ? valueIfTrue : valueIfFalse;
The even/odd check from Example 1 rewrites cleanly:
let num = 14;
let label = (num % 2 === 0) ? "even" : "odd";
console.log(label);
// Output: even
A common pattern is returning early from a function:
function getDiscount(isMember) {
return isMember ? 0.2 : 0;
}
console.log(getDiscount(true)); // 0.2
console.log(getDiscount(false)); // 0
You can chain ternaries to replicate an else if ladder, but it gets unreadable fast:
// readable as a one-off, messy if you add more branches
let grade = score >= 90 ? "A" : score >= 75 ? "B" : "C";
Stick to one level. If you need three or more branches, write the else if ladder. It’s faster to scan and easier to debug.
Nullish coalescing: default values without the if else
The nullish coalescing operator ?? (double question mark) returns the right-hand value when the left-hand value is null or undefined. Everything else passes through unchanged, including 0, false and "".
let username = null;
let display = username ?? "Guest";
console.log(display); // "Guest"
Why this matters: the || operator also provides a fallback, but it triggers on any falsy value. That silently swallows 0 and "" when those are legitimate values:
let count = 0;
// OR triggers on 0 (falsy), returns "none" even though 0 is a valid count
let withOR = count || "none"; // "none" -- probably wrong
// ?? only triggers on null/undefined
let withNC = count ?? "none"; // 0 -- correct
In practice ?? replaces a common if else pattern:
// if else version
let port;
if (config.port !== null && config.port !== undefined) {
port = config.port;
} else {
port = 3000;
}
// nullish coalescing version
let port = config.port ?? 3000;
You can also use the nullish coalescing assignment ??= to set a default only if a variable is currently null or undefined:
let settings = { theme: null };
settings.theme ??= "dark";
console.log(settings.theme); // "dark"
Optional chaining: safe property access without nested ifs
Optional chaining ?. short-circuits to undefined if the left side is null or undefined, rather than throwing a TypeError. Before it existed, reading a deeply nested property safely meant a chain of if checks:
// the old way: verbose and fragile
let city;
if (user && user.address && user.address.city) {
city = user.address.city;
}
// with optional chaining
let city = user?.address?.city;
If user is null, user?.address returns undefined and the chain stops there without an error.
You can also call optional methods:
let result = someObject?.doSomething?.();
And access array indices optionally:
let first = arr?.[0];
Combining ?. and ?? is where the real payoff is. You get safe access and a fallback in one expression:
const user = { profile: null };
// Safe access + fallback default
const city = user?.profile?.city ?? "Unknown";
console.log(city); // "Unknown"
Before optional chaining and nullish coalescing, that same result took four or five lines of if else. Now it’s one readable line. Both operators are supported in all modern browsers and Node.js 14+.
if else vs switch: when to use which
Both control flow, but they serve different shapes of logic.
Use if else when:
- Conditions compare different variables or expressions
- You need range checks (
score >= 60 && score < 80) - You’re combining logical operators (
&&,||) - The branching logic is complex or heterogeneous
Use switch when:
- You’re matching one variable against a list of discrete values
- Readability matters and you have five or more branches
- You want fall-through behavior across cases
A key difference: switch uses strict equality (===) for matching, so it won’t match the string "1" against the number 1. Prefer === in your if else conditions too, for the same predictability.
Another difference is performance at scale. When you have many branches, the JavaScript engine can compile a switch into a jump table and skip straight to the matching case. An if else chain evaluates conditions top to bottom every time, which adds up when running in a hot loop. For typical application code this doesn’t matter, but it’s worth knowing when optimizing performance-sensitive paths.
// if else: better for ranges
if (score >= 90) {
grade = "A";
} else if (score >= 75) {
grade = "B";
} else {
grade = "C";
}
// switch: better for discrete values
switch (day) {
case "Monday":
console.log("Start of the week.");
break;
case "Friday":
console.log("Almost there.");
break;
default:
console.log("Midweek.");
}
Common pitfalls
Assignment instead of comparison
if (x = 10) assigns 10 to x, then evaluates x as truthy. The condition always passes. Always use == for loose equality or === for strict equality inside a condition.
// Wrong: assigns, doesn't compare
if (x = 10) { ... }
// Correct
if (x === 10) { ... }
Enabling strict mode with "use strict" turns accidental assignments in conditions into a syntax error, which is one reason to use it.
Semicolon after the condition
if (score > 50); // <-- semicolon ends the statement here
{
console.log("Passed."); // runs unconditionally
}
The block runs regardless of the condition because the semicolon creates an empty statement. The block after it is just a labeled block, not the body of the if. Linters catch this. ESLint’s no-extra-semi rule flags it.
Forgetting that objects and arrays are always truthy
const arr = [];
if (arr) {
console.log("This runs."); // it does
}
An empty array is truthy. So is an empty object. If you mean to check for content, check arr.length or use Object.keys(obj).length.
Key Takeaways
ifexecutes a block when the condition is truthy,elsehandles the false branchelse ifchains let you evaluate multiple conditions in order, first true match wins- JavaScript’s falsy values are
false,0,-0,0n,"",null,undefinedandNaN. Everything else is truthy - Always use curly braces around blocks. Omitting them causes the dangling else bug
- Logical operators
&&,||and!compose conditions without nesting - The ternary operator
condition ? a : breplaces a simple two-branchif else - The nullish coalescing operator
??sets defaults only fornullorundefined, not all falsy values - Optional chaining
?.safely traverses nested properties without guarding every level withif - Use switch over
if elsewhen testing one variable against many discrete values - Never use
=inside a condition. Use===for strict comparison
Frequently Asked Questions
What is the JavaScript if else statement?
The if else statement runs one block of code when a condition is truthy and a different block when it is falsy.
How does JavaScript evaluate conditions in an if statement?
JavaScript converts the condition to a boolean. Falsy values (false, 0, "", null, undefined, NaN) give false. Everything else gives true.
What is the difference between == and === in an if condition?
== coerces types before comparing, so "5" == 5 is true. === checks type and value, so "5" === 5 is false. Prefer === to avoid surprises.
Can you use multiple conditions in a single if statement?
Yes. Use && to require all conditions to be true or || to require at least one to be true.
When should I use else if instead of nested if?
Use else if when conditions are mutually exclusive. Use nested if only when a second decision depends on the first condition already being true.
What is the dangling else problem in JavaScript?
When you omit curly braces, an else binds to the nearest if, not the outer one, causing logic bugs. Always use braces to make binding explicit.
Is switch faster than if else in JavaScript?
For a small number of branches the difference is negligible. For many discrete values, switch can be faster because the engine generates a jump table. The if else chain evaluates conditions top to bottom every time.
What is the difference between ?? and || in JavaScript?
|| returns the right side for any falsy value including 0, false and "". ?? only returns the right side when the left side is null or undefined, so 0 ?? "default" gives 0.
What does optional chaining do in JavaScript?
?. returns undefined instead of throwing a TypeError when accessing a property on null or undefined. It short-circuits the rest of the chain, so user?.address?.city is safe even if user is null.
The three examples above cover the most common patterns you’ll see in real code: parity checks, time-based branching and multi-condition classification. From here, check out the JavaScript arrays guide and the JavaScript string interpolation article for putting conditional output directly into template literals.


