Learning Goals
3 minBy the end of this lesson you will be able to:
- Write a function that takes parameters and
returns a value. - Explain the difference between printing and returning.
- Write the same function in the arrow style.
- Call one function from inside another to build a small calculator.
Warm-Up · The Same Sum, Three Times
5 minLoops repeat identical work. But sometimes you need the same calculation on different values, in different places.
const aisyahBill = 20 + 20 * 0.1;
const weiJieBill = 35 + 35 * 0.1;
const priyaBill = 12 + 12 * 0.06;Predict together
- What is the same in all three lines, and what differs?
- Line 3 uses a different rate. Is that on purpose, or a typo?
Reveal
The shape is identical — amount plus service charge. Only the amount and rate differ. And nobody can tell whether the 0.06 is deliberate or a slip, because the rule is written out three times instead of stated once. A function fixes exactly this.
New Concept · A Recipe You Can Reuse
12 minA teh tarik recipe says: take tea, add milk, pull it. It does not say which cup. You supply the cup each time you follow it. A function works the same — the steps are fixed, the ingredients change.
Declaring and calling
function addService(amount) {
return amount + amount * 0.1;
}
console.log(addService(20));
console.log(addService(35));22
38.5Four pieces of vocabulary, all visible above:
functionaddServiceamount20A parameter is the blank in the recipe. An argument is what you actually pass in when you call it.
Return is not print
This is the idea most people trip over. console.log() shows a value to a human. return hands a value back to your code.
return
Gives the answer back to whoever called.
You can store it, add to it, pass it on.
Nothing appears on screen.
console.log
Displays it and moves on.
The value is gone — nothing to reuse.
The function hands back undefined.
function printService(amount) {
console.log(amount * 1.1); // shows it, returns nothing
}
const result = printService(20);
console.log('Stored value:', result);22
Stored value: undefinedThe 22 appeared, but result is undefined — the value was never handed back. As a rule: functions that calculate should return, and the code that called them decides whether to print.
Several parameters, and defaults
function billTotal(amount, rate = 0.1) {
return amount + amount * rate;
}
console.log(billTotal(20)); // uses the default 0.1
console.log(billTotal(12, 0.06)); // overrides it22
12.72Now the 6% rate in the Warm-Up is obviously deliberate — it is passed in on purpose, not buried in a repeated sum.
Arrow functions
There is a shorter style you will see constantly in React. Same job, less typing.
const billTotal = (amount, rate = 0.1) => {
return amount + amount * rate;
};
// one expression? drop the braces and the return
const double = (n) => n * 2;
console.log(billTotal(20), double(7));22 14Use whichever reads better. This course follows the common convention: function declarations for top-level helpers, and arrows for small callbacks — which is exactly what Lesson 10 needs.
Why it matters
Functions are the unit of reuse in every language. And in React a component is literally a function — it takes details in and returns something to show. Everything here comes back in Section D.
Worked Example · A Bill Calculator
12 minBuild a small set of functions in bill.js that work together.
Step 1 — One job, one function
// bill.js — Warung Aisyah's till
const SERVICE_RATE = 0.1;
function serviceCharge(amount) {
return amount * SERVICE_RATE;
}
console.log(serviceCharge(30));3Step 2 — Build on it
A function can call another. Keep each one doing a single job:
function grandTotal(amount) {
return amount + serviceCharge(amount);
}
console.log(grandTotal(30));33Step 3 — A function that formats
Formatting is its own job, so give it its own function. It returns a string, using .toFixed(2) from Lesson 4:
function asRinggit(amount) {
return `RM ${amount.toFixed(2)}`;
}
console.log(asRinggit(grandTotal(30)));RM 33.00Read the last line inside out: grandTotal(30) runs first and returns 33, then asRinggit(33) turns it into text. This only works because both functions return.
Step 4 — Use it in a loop
Three customers, one function, no repetition:
const bills = [20, 35, 12];
for (let i = 0; i < bills.length; i++) {
const before = bills[i];
console.log(`${asRinggit(before)} becomes ${asRinggit(grandTotal(before))}`);
}RM 20.00 becomes RM 22.00
RM 35.00 becomes RM 38.50
RM 12.00 becomes RM 13.20That square-bracket list is an array — the whole of next lesson. For now, note that bills[i] reads the item at position i.
Step 5 — Change the rule once
The government raises service charge to 12%. Change SERVICE_RATE to 0.12 and run it again:
RM 20.00 becomes RM 22.40
RM 35.00 becomes RM 39.20
RM 12.00 becomes RM 13.44What changed? One character, and every total updated. Compare that with the Warm-Up, where the rule was copied three times. This is the real payoff of naming a job.
Try It Yourself
13 minWork in bill.js or a new functions.js.
Task 1 — A greeting function
Write
greet(name, town)that returns (not prints) a welcome sentence using a template literal. Call it three times with different Malaysian names and towns, printing each result.Task 2 — Discount with a default
Write
applyDiscount(price, percent = 10)that returns the new price. Call it once using the default, and once with 25.Then reuse your
asRinggit()function to print both nicely.Task 3 — Convert it to an arrow
Rewrite both of your functions in the arrow style. Check the output is identical.
Then write a one-line arrow
isExpensivethat returnstruewhen a price is over RM 50. It should fit on a single line with no braces.
🔥 Mini-Challenge · The Function That Gives Nothing Back
8 minKarthik's delivery calculator prints NaN. Find two mistakes.
// karthik-delivery.js — buggy
function deliveryFee(distanceKm) {
console.log(distanceKm * 1.2);
}
function orderTotal(food, distanceKm) {
const fee = deliveryFee(distanceKm);
return food + fee;
}
const total = orderTotal(24, 5);
console.log('Total: RM ' + total.toFixed(2));It works if: the console prints Total: RM 30.00 — RM 24 of food plus RM 6 delivery for 5 km.
Reveal the answer
Mistake 1 — printing instead of returning.
deliveryFee logs the fee but never returns it, so it hands back undefined. Then 24 + undefined is NaN, and NaN.toFixed(2) prints NaN:
6
Total: RM NaNThe stray 6 on the first line is the giveaway — the value existed, it just never came back.
Mistake 2 — a magic number.
1.2 appears with no explanation. Nobody reading this knows it is the per-kilometre rate. Name it.
// karthik-delivery.js — fixed
const RATE_PER_KM = 1.2;
function deliveryFee(distanceKm) {
return distanceKm * RATE_PER_KM; // return, don't print
}
function orderTotal(food, distanceKm) {
return food + deliveryFee(distanceKm);
}
const total = orderTotal(24, 5);
console.log(`Total: RM ${total.toFixed(2)}`);Total: RM 30.00Whenever a function is meant to give you an answer, look for the word return. If it is missing, you will get undefined — and shortly afterwards, NaN.
Recap
3 min- A function is a named, reusable job.
- Parameters are the blanks; arguments are what you pass in.
returnhands a value back;console.logonly shows it.- A function with no
returngives youundefined— and thenNaN. - Default parameters (
rate = 0.1) make the common case tidy. - Arrow functions are a shorter style; a one-expression arrow needs no braces or
return. - One function, one job. Small functions combine well.
New words
- Function — a named block of reusable code.
- Parameter / argument — the blank, and the value filling it.
- Return value — what a function hands back.
- Arrow function — the
=>shorthand style.
📦 Homework
4 min to brief · ~20 min to doRequired
- Write
cinema.jswith three functions:ticketPrice(age)returning a fare,bookingFee(tickets)returning RM 1 per ticket, andtotal(age, tickets)that uses both. Every one must return. - Print the total for three different customers. Bring the file next lesson.
Optional stretch
- Rewrite all three as arrow functions. Which style do you find easier to read? One sentence.
- What happens if you call
ticketPrice()with no argument at all? Try it, read the result, and add a default so it behaves sensibly.