DataLens

Conditionals and loops

Make decisions with if, else, the ternary operator and switch, understand truthy and falsy values, guard against missing data with ?? and ?., and repeat work with for, for...of and while.

Level: Foundations · 9 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

Programs become useful when they decide (is this order eligible for free shipping?) and repeat (add up every item in the cart). JavaScript's tools for both look like most C-style languages: curly braces and round brackets instead of Python's indentation. The logic is the same; the traps are different, especially around which values count as "true".

if, else if, else

Toko Kita's shipping rule has three tiers: free for orders of 300000 or more, 10000 from 150000, and 20000 for anything smaller. That's a chain of decisions, and it looks almost the same as Python's if/elif/else, just with brackets and curly braces:

function shippingFee(total) {
  if (total >= 300000) {
    return 0;
  } else if (total >= 150000) {
    return 10000;
  } else {
    return 20000;
  }
}

console.log(shippingFee(450000), shippingFee(200000), shippingFee(50000));
0 10000 20000

Conditions go in round brackets, blocks in curly braces. Order matters: the first true condition wins, so check the most specific case first.

The ternary operator

For choosing between two values, there's a one-line form: condition ? valueIfTrue : valueIfFalse.

const stock = 0;
const label = stock > 0 ? "In stock" : "Sold out";
console.log(label);
Sold out

Use it for simple value choices. For anything with more than two branches or side effects, if reads better.

Truthy and falsy

if accepts any value, not only booleans. These six values count as false (they're "falsy"): false, 0, "" (empty string), null, undefined and NaN. Everything else is truthy, including "0", [] and {}.

const checks = [0, "", "0", [], null, "Ayu"];
for (const value of checks) {
  console.log(JSON.stringify(value), value ? "truthy" : "falsy");
}
0 falsy
"" falsy
"0" truthy
[] truthy
null falsy
"Ayu" truthy

The trap: an empty array is truthy, unlike Python. Check cart.length > 0, not if (cart).

Guarding against missing data: ?? and ?.

Data from forms and servers is often incomplete. A customer hasn't set a nickname, or hasn't entered an address yet. In JavaScript, reading something that doesn't exist gives you undefined or null, and trying to go one step further, like reading the city of a missing address, crashes the page. Two small operators handle this safely:

const user = { name: "Ayu", address: null, settings: { currency: "IDR" } };

console.log(user.nickname ?? user.name);          // ?? : use the right side if the left is null/undefined
console.log(user.address?.city);                  // ?. : stop safely if address is null
console.log(user.settings?.currency ?? "IDR");

const discount = 0;
console.log(discount || 10, discount ?? 10);      // || treats 0 as missing; ?? doesn't
Ayu
undefined
IDR
10 0

switch

switch compares one value against several options with ===:

function roastNote(roast) {
  switch (roast) {
    case "light":
      return "Bright and fruity";
    case "medium":
      return "Balanced and sweet";
    case "dark":
      return "Bold and smoky";
    default:
      return "Unknown roast";
  }
}

console.log(roastNote("medium"), "|", roastNote("extra"));
Balanced and sweet | Unknown roast

Inside a function, return ends each case. Outside one, each case needs a break, or execution "falls through" into the next case. A lookup object (const notes = { light: "...", dark: "..." }; notes[roast] ?? "Unknown") is often cleaner.

Loops

Most of the work in a shop page is going through lists: every item in the cart, every product in a category. JavaScript has a few kinds of loop, and this example uses the three you'll meet most often, on a small cart:

const cart = [
  { name: "Arabica Gayo", price: 95000 },
  { name: "Paper filters", price: 35000 },
  { name: "French Press", price: 245000 },
];

for (let i = 0; i < cart.length; i++) {          // classic counter loop
  console.log(i + 1, cart[i].name);
}

for (const item of cart) {                        // for...of: each value
  if (item.price < 50000) continue;               // skip this one
  console.log("Premium:", item.name);
}

let stock = 10;
let days = 0;
while (stock > 0) {                               // repeat while a condition holds
  stock -= 3;
  days++;
}
console.log("Sold out after", days, "days");
1 Arabica Gayo
2 Paper filters
3 French Press
Premium: Arabica Gayo
Premium: French Press
Sold out after 4 days

Avoid for...in on arrays: it loops over keys (as strings), not values. It's meant for objects, and even there Object.entries(obj) with for...of is clearer.

Key idea

if/else if/else for branches, the ternary for choosing values, switch or a lookup object for many fixed options. Remember the six falsy values, and that [] is truthy. Use ?? and ?. for missing data. Loop with for...of by default.

Why this matters for clean code

Return early to keep code flat: if (!user) return; at the top beats wrapping the whole function in an if. Prefer ?? over || for defaults so valid zeros survive. And when a chain of ifs maps fixed values to results, a lookup object turns ten lines of branching into data.

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: The DOM: selecting and changing elements →