Tutorials Logic, IN info@tutorialslogic.com

JavaScript if else Statement

JavaScript Branching

JavaScript conditions convert values to boolean unless an explicit comparison already produces one. Falsy values include false, 0, -0, 0n, an empty string, null, undefined, and NaN; empty arrays and objects are truthy. Use strict equality when comparing values with known types.

Conditional Statements

A conditional statement refers to a piece of code that does the things based on some condition. When we write code, we will often need to use these conditional statements. There are besically four types of conditional statements-

  • The if statements.
  • The if-else statements.
  • The if-else-if statements.
  • The switch case statements.

if Statement

The if statement is used to execute a block of code only if the specified condition is true.

Javascript Conditional Statements Syntax

Javascript Conditional Statements Syntax
if(condition) {
	statement;
}

Javascript Conditional Statements Worked Example

Javascript Conditional Statements Worked Example
if(7 > 5) {
	console.log('True');
}

if-else Statement

Javascript Conditional Statements Syntax 2

Javascript Conditional Statements Syntax 2
if(condition) {
	statement 1;
} else {
	statement 2;
}

Javascript Conditional Statements Worked Example 2

Javascript Conditional Statements Worked Example 2
if(5 > 7) {
	console.log('True');
} else {
	console.log('False');
}

else-if Chains

The if-else-if statement is used to execute a block of code only if the specified condition is true from the several condition.

Javascript Conditional Statements Syntax 3

Javascript Conditional Statements Syntax 3
if(condition) {
	statement 1;
} else if {
	statement 2;
} else {
	statement 3;
}

Javascript Conditional Statements Worked Example 3

Javascript Conditional Statements Worked Example 3
if(5 > 7) {
	console.log('Greater');
} else if (5 == 7) {
	console.log('Equals');
} else {
	console.log('Smaller');
}

switch Statement

The switch case statement evaluates an expression, and then matching its value to a case clause, once match case is found, it executes statements associated with that case.

Javascript Conditional Statements Syntax 4

Javascript Conditional Statements Syntax 4
switch(expression) {
	case value 1:
	    statement;
		break;

	case value 2:
	    statement;
		break;

	default:
	    statement;
}

Javascript Conditional Statements Worked Example 4

Javascript Conditional Statements Worked Example 4
let value = 2;

switch (value) {
	case 1:
	    console.log('Too small');
		break;
	case 2:
	    console.log('Exactly!');
		break;
	case 3:
	    console.log('Too large');
		break;
	default:
	    console.log('Unknown');
}

Conditional Operator

The ternary operator is a concise one-liner alternative to if-else for simple conditions.

Ternary Operator

Ternary Operator
// Syntax: condition ? valueIfTrue : valueIfFalse
const age = 20;
const status = age >= 18 ? 'Adult' : 'Minor';
console.log(status); // Adult

// Nested ternary (use sparingly - can reduce readability)
const score = 75;
const grade = score >= 90 ? 'A'
            : score >= 80 ? 'B'
            : score >= 70 ? 'C'
            : 'F';
console.log(grade); // C

// Ternary in JSX / template literals
const isLoggedIn = true;
const message = `Welcome, ${isLoggedIn ? 'User' : 'Guest'}!`;
console.log(message); // Welcome, User!

Grade Calculator Example

Grade Calculator

Grade Calculator
function getGrade(score) {
  if (score < 0 || score > 100) {
    return 'Invalid score';
  } else if (score >= 90) {
    return 'A - Excellent';
  } else if (score >= 80) {
    return 'B - Good';
  } else if (score >= 70) {
    return 'C - Average';
  } else if (score >= 60) {
    return 'D - Below Average';
  } else {
    return 'F - Fail';
  }
}

console.log(getGrade(95));  // A - Excellent
console.log(getGrade(72));  // C - Average
console.log(getGrade(45));  // F - Fail

// Same logic with switch on grade band
function getDayName(day) {
  switch (day) {
    case 1: return 'Monday';
    case 2: return 'Tuesday';
    case 3: return 'Wednesday';
    case 4: return 'Thursday';
    case 5: return 'Friday';
    case 6: return 'Saturday';
    case 7: return 'Sunday';
    default: return 'Invalid day';
  }
}
console.log(getDayName(5)); // Friday

Readable Branches

Use if/else for ranges and compound predicates, switch for one value matched against several strict case values, and a ternary for one small value choice. Avoid nested ternaries and assignment inside conditions because they hide control flow.

The nullish coalescing operator supplies a fallback only for null or undefined, while || also replaces valid falsy values such as 0 and an empty string. Choose based on the data contract, and test boundary and missing-value cases.

Conditions and Truthiness

An `if` condition converts its expression to boolean. The falsy values are `false`, `0`, `-0`, `0n`, an empty string, `null`, `undefined`, and `NaN`; every object and array is truthy, including an empty one. Write the business condition explicitly when zero, an empty string, or a missing value have different meanings.

Prefer strict equality because it compares without the broad type coercion performed by `==`. Intentional loose equality is rare and needs a clear contract. `Object.is` differs for `NaN` and signed zero, while arrays and objects compare by identity. Two separately created objects with the same properties are not equal references.

The logical operators return operands, not normalized booleans. `a && b` returns the first falsy operand or `b`; `a || b` returns the first truthy operand; `a ?? b` falls back only for `null` or `undefined`. Use `??` when zero, `false`, and an empty string are valid values.

Optional chaining stops a property access or call when its left side is nullish. It does not validate the final type or catch an exception thrown by a method. Combine it with a deliberate default and validation rather than letting missing required data pass silently.

  • Name the exact empty and missing states the branch accepts.
  • Use strict equality for ordinary value comparisons.
  • Choose logical OR or nullish coalescing from the data contract.
  • Test objects, zero, empty strings, null, undefined, and NaN where relevant.

Branch Structure and Reachability

An `if` and `else if` chain selects the first true branch, so order is part of the algorithm. Place narrower conditions before broader overlapping conditions or make the ranges mutually exclusive. A final `else` is useful only when every remaining value has the same meaning; otherwise report or reject the unexpected case.

Guard clauses handle invalid input, missing authorization, unavailable state, or completed work early. They reduce nesting when each guard exits with `return`, `throw`, `continue`, or `break`. Keep validation and side effects separate so a later guard does not run after an earlier branch already modified durable state.

Braces prevent maintenance errors even around a one-line body. Automatic semicolon insertion and misleading indentation can make an unbraced branch look different from its actual scope. Use a formatter and linter, but keep the source structurally clear without relying on color or indentation alone.

The conditional operator is an expression and works well for selecting one compact value. Nested ternaries and branches that perform several side effects are harder to scan and debug. Extract a named decision function or use ordinary statements when the decision needs explanation, logging, or several steps.

  • Order overlapping rules from specific to general.
  • Exit guard clauses before any protected side effect.
  • Use braces consistently.
  • Reserve ternaries for concise value selection.

Switches and Decision Models

A `switch` evaluates its discriminant once and compares case values using strict equality. Execution continues from the matching label until a `break`, `return`, `throw`, or the end, so accidental fall-through is a common bug. Intentional fall-through should group labels visibly or carry a short reason.

Use a switch for a closed set of discrete states such as command type or lifecycle status. Use ranges and compound predicates in `if` statements. For a data-driven mapping from stable keys to values or handlers, an object or `Map` can remove repetitive case syntax, but validate the key and avoid invoking inherited properties accidentally.

A `default` branch should not hide a new unsupported state. In codebases with static analysis, use an exhaustive assertion that fails when a new variant is not handled. In plain JavaScript, validate external input at the boundary and throw or return a structured error for an impossible internal state.

Decision tables help when several independent conditions interact. List each input dimension, valid combination, outcome, and priority before writing branches. The table reveals missing and contradictory rules and can drive parameterized tests without duplicating the implementation logic in the test.

  • Use switches for discrete equality-based choices.
  • Make every fall-through intentional and visible.
  • Reject unknown internal states rather than choosing a silent default.
  • Model multi-input business rules in a decision table.

Testing and Debugging Branches

Branch coverage proves that each branch ran, not that every boundary and combination is correct. Test values immediately below, at, and above numeric thresholds; test empty and missing forms separately; and include overlapping rules. Mutation testing can reveal assertions that execute a branch but do not detect an inverted comparison.

When a branch never runs, inspect the actual value and type, the earlier branches that may already match, and any coercion in the predicate. Log named input facts rather than only “condition false.” A debugger conditional breakpoint can stop on the exact combination without adding permanent output to a hot loop.

Keep predicate functions pure where practical. A function such as `canPublish(user, article)` is easier to test than a condition that fetches data, updates counters, and checks authorization at once. Return a reason object when the interface must explain denial, but do not expose sensitive internal policy details to an untrusted caller.

For critical authorization and pricing logic, test denied paths, stale state, missing claims, clock boundaries, and concurrent change. The client can improve user experience, but the trusted server must repeat security decisions. A disabled button is not an access-control branch.

  • Test boundary values and combinations, not only happy examples.
  • Inspect both runtime value and type during diagnosis.
  • Extract pure predicates from side-effecting workflows.
  • Enforce security decisions again at the trusted boundary.

Decision Outcomes and Policy

A boolean is sufficient when callers only need yes or no. When they must render a message, choose a recovery action, or create audit evidence, return a structured outcome such as `{ allowed: false, code: "PLAN_LIMIT", retryable: false }`. Keep the stable machine code separate from localized text, and avoid returning internal security details that help an attacker map policy.

Separate validation from authorization and eligibility. Validation asks whether input has the required shape and values. Authorization asks whether the authenticated actor may perform the action on this resource. Eligibility applies business rules such as plan, date, inventory, or workflow state. One broad condition that mixes all three produces vague errors and makes policy changes risky.

Evaluate conditions from trusted, current facts. Client state can be stale or modified, cached permissions may outlive membership changes, and local time can differ from server time. The trusted service should load the authoritative record, bind it to the actor and tenant, evaluate the rule, and commit under a transaction or concurrency check when the state can change between decision and write.

Record which policy version and material facts produced a sensitive decision, while minimizing personal data. This supports incident review without logging secrets or full records. Re-evaluate long-running workflows at the point of irreversible action; approval at screen load does not guarantee the same authorization or inventory remains valid minutes later.

  • Return stable reason codes when callers need more than a boolean.
  • Keep validation, authorization, and business eligibility distinct.
  • Evaluate critical decisions against authoritative current state.
  • Recheck policy before irreversible side effects.
  • Log decision evidence without exposing sensitive policy internals.
Before you move on

JavaScript if else Statement Mastery Check

3 checks
  • A conditional statement refers to a piece of code that does the things based on some condition.
  • When we write code, we will often need to use these conditional statements.
  • JavaScript provides if, if-else, else-if chains, and switch statements for branching.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.