Name a Reporting Rule and Call It

You can already count the messages about one topic: a loop walks through the records, and a condition picks the ones that match. Now someone asks for a second report, this time about billing. The quickest move is to copy the block that works and change the topic and counter name:

Language: JavaScript
const messages = [
  { id: "M-101", topic: "delivery", text: "Box came late" },
  { id: "M-102", topic: "billing", text: "Charged twice" },
  { id: "M-103", topic: "delivery", text: "Wrong address" },
];

let deliveryCount = 0;
for (const message of messages) {
  if (message.topic === "delivery") {
    deliveryCount = deliveryCount + 1;
  }
}
console.log("delivery", deliveryCount);

let billingCount = 0;
for (const message of messages) {
  if (message.topic === "billing") {
    billingCount = billingCount + 1;
  }
}
console.log("billing", billingCount);
Language: Program Output
delivery 2
billing 1

Both counts are right, so what’s the problem? Picture a third topic, then a fifth. Each copy is its own version of the rule. If the rule changes later, you have to find and fix every copy, and the one you forget quietly reports something different from the others.

In this lesson, you’ll write the counting rule once, give it a name, and run it for any topic you like.

This course assumes you can count and select records with a loop and a condition; Select and Count Feedback is a useful starting point if those are new. You’ll read examples, predict results, then write and test your own functions in the browser. The first exercise explains the controls again, so you can start here even if this is your first RealJS course.

For this course, assume the supplied topics have already been reviewed. These records therefore omit status: the lesson is about organizing reusable functions. The approved-only rule from the previous course has not become unnecessary; a dataset with unchecked labels would still need it.

Read the Function Wrapper You Already Know

You’ve met this idea before. In earlier exercises, the starter code wrapped your work in a few lines of its own, something like this:

Language: JavaScript
function countDelivery(messages) {
  let count = 0;
  for (const message of messages) {
    if (message.topic === "delivery") {
      count = count + 1;
    }
  }
  return count;
}

That wrapper is a function declaration. It starts with the function keyword, then the function’s name, countDelivery. Between the curly braces sits the body: the code that runs when someone uses the function.

The messages in parentheses is a parameter, a name for a value the function receives from outside. The body never says where the array comes from. It only promises to work with whatever arrives under that name. The return line hands the count back to whoever asked for it, and you’ll write lines like that yourself two lessons from now.

So who used the function? The exercise did. When you pressed Run, the exercise called your function with its own array, in a line like countDelivery(sampleMessages). The value it passed in, sampleMessages, was the argument, and inside the body it went by the parameter’s name, messages. That’s how the same code could be checked against data you never saw.

Declare Your Own Reporting Function

Now it’s your turn to write the wrapper. This function takes two parameters, the records and the topic to look for, and logs the count:

Language: JavaScript
function logTopicCount(messages, topic) {
  let count = 0;
  for (const message of messages) {
    if (message.topic === topic) {
      count = count + 1;
    }
  }
  console.log(topic, count);
}

The condition no longer names a topic. It compares each message’s topic with the topic parameter, so the caller decides which topic counts. The function’s name, logTopicCount, is a verb phrase in camelCase, which starts lowercase and capitalizes each later word, so a call reads like an instruction.

Keep in mind that this declaration on its own prints nothing. Writing it down is like writing a recipe without cooking the meal: the body waits until something calls the function.

Call It With Different Arguments

To use your function, write its name, then parentheses with one argument for each parameter. Here’s the whole program, with the data, the declaration, and three calls. Read it and predict what each call logs before you look at the output:

Language: JavaScript
const messages = [
  { id: "M-101", topic: "delivery", text: "Box came late" },
  { id: "M-102", topic: "billing", text: "Charged twice" },
  { id: "M-103", topic: "delivery", text: "Wrong address" },
];

function logTopicCount(messages, topic) {
  let count = 0;
  for (const message of messages) {
    if (message.topic === topic) {
      count = count + 1;
    }
  }
  console.log(topic, count);
}

logTopicCount(messages, "delivery");
logTopicCount(messages, "billing");
logTopicCount(messages, "app");
Language: Program Output
delivery 2
billing 1
app 0

Nice! Three reports, one rule. Each call jumps into the body with its own arguments, runs it to the end, and then comes back to the next line. JavaScript matches arguments to parameters by position: the first argument becomes messages, the second becomes topic.

The app report shows 0, which is correct, because none of the three messages is about the app. And when the counting rule needs to change, you change it in one place, and every report follows.

As a rule of thumb, declare a function above the code that calls it, so anyone reading your program meets the rule before its first use.

You’ll type code like this into RealJS exercises, as before. The starter supplies a function, and the website calls it with its own data, just as it called countDelivery(). You type your declaration above that supplied function. Inside the supplied function’s body, you write the calls to your function yourself, passing the data that the supplied function received as arguments. The website never calls your function directly.

Use Run to execute the calls you write and inspect their logged output. Use Run Tests to have the website call the supplied function on its test inputs and check your answer. If you haven’t added any calls of your own, a Run can show no output even though the declarations are valid. In the next exercise, run the tests after each change and read the first relevant failure. You can expand the editor with Full screen.

Before you move on, look back at the two copied blocks at the top of this lesson. Keep the messages array and add the logTopicCount() declaration from the complete program, and write the two complete calls that replace both blocks. Then compare your answer with these calls:

Language: JavaScript
logTopicCount(messages, "delivery");
logTopicCount(messages, "billing");

In both calls, the first argument, messages, becomes the messages parameter, and the second becomes topic. So the first call logs delivery 2 and the second logs billing 1, the same lines the copied blocks printed.

In the next exercise, Turn a Copied Block Into a Function, you’ll refactor two copied summary blocks into one function and call it on two datasets.

Become a Member to join the conversation.