Aabha · Learn by building

04. Turn a rule into a function

Give a useful operation a name

We have written a rule that turns a remaining-seat count into a label. Soon we will need it for several event cards. Copying the rule into every card would create multiple places to fix a mistake. A function packages the operation under one name. Inputs arrive as parameters; a result can leave through return.

function seatLabel(remaining) {
  if (remaining < 0) {
    return "Check the event data";
  }
  if (remaining === 0) {
    return "Full";
  }
  return `${remaining} places available`;
}
const label = seatLabel(7);
console.log(label);

A function declaration defines the operation; it does not run its body immediately. seatLabel(7) calls it. The number 7 is an argument for this call and becomes the local parameter named remaining. The function chooses a return statement and passes its result to the caller. The caller assigns that result to label. The braces belong to the function body, and return exits that body immediately.

Trace the boundary between caller and function

Follow seatLabel(0) carefully. The call supplies 0. The first comparison is false. The second is true, so the function returns Full. The final template literal is never evaluated for this call. Now imagine that the function only calls console.log("Full") instead. A message would appear, but the caller would receive undefined because no value was returned. Logging is an observation; returning is part of the program's data flow.

A call sends 7 into seatLabel and receives the string 7 places available

An input/output table makes the contract visible: -1 gives Check the event data; 0 gives Full; 1 gives 1 places available in this first simple implementation; 7 gives 7 places available. The slightly awkward singular case is a useful exercise. First get the logic right; then improve the wording with a separate branch and matching test.

Scope keeps temporary names local

Scope describes where a name can be used. A parameter and a const declared inside a function belong to that function's scope. A let or const inside an if block belongs to that block. Code outside cannot rely on those local names. This protects different parts of the program from accidentally sharing temporary work.

function remainingPlaces(capacity, interested) {
  const difference = capacity - interested;
  return difference;
}
const available = remainingPlaces(12, 5);
// difference is not available here; available is 7.

Use parameters to pass information in and return values to send results out. A function that reads and changes many distant variables is harder to test because its behavior depends on hidden context. A pure calculation such as remainingPlaces is easy to check: the same inputs produce the same result and it changes nothing else. Later, a rendering function will intentionally change the page. We will keep those responsibilities separate where it helps.

Functions are values too

An event listener will need a function to run later. JavaScript lets you pass a function itself as a value. The difference between seatLabel and seatLabel(7) is therefore important: one refers to the function; the other calls it now and produces a result. A callback is simply a function supplied to another operation to be called by that operation.

You will also see arrow functions:

const double = (number) => number * 2;
console.log(double(3)); // 6

For this small calculation, the expression after the arrow is returned automatically. If you use a body with braces, write return explicitly. This course uses ordinary declarations for substantial named operations and short arrows for callbacks. Arrow functions have other differences, including how they handle this; we do not need those differences for this project. Do not assume every function form is interchangeable in all programs.

A repair routine

Run version 04. Change the final return to a console.log and observe what the outer caller receives. Restore it. Then call remainingPlaces with the arguments swapped. The program runs, but its answer changes. A runtime that accepts code does not know your intended meaning; descriptive names and tests help catch that sort of error.

If you find yourself adding many optional parameters, stop and state the function's one job. For this course, small focused functions are easier to learn from than a universal “handle everything” function. In lesson 05, we will apply callbacks to collections while retaining these input/output habits.

Reference: MDN functions.

Practice and next step

Open exercise 04. Attempt the prediction before running code. Record the observed result and explain any mismatch. The explained solution is separate so you can choose when to look.