Lesson 3 of 5 · Client-Side Logic
Functions & Arrays
Functions are reusable recipes; arrays are ordered lists. Together they turn one-off scripts into real programs.
This lesson is locked. You can read ahead, but finish earlier stops to earn progress.
Listen
Watch
Read
Give repeated work a name
A function groups a set of steps so you can call them again with new inputs. Defining it does not run it:
function lineCost(price, quantity) {
const result = price * quantity;
return result;
}
const first = lineCost(12, 2);
const second = lineCost(3, 4);
console.log(first, second);Price and quantity are parameters. The values 12 and 2 are arguments passed in one call. The first call returns 24; the second returns 12. Each call has its own local parameters/result. return sends a value back and stops that function; console.log merely prints, so logging a total is not the same as returning it for another calculation.
A function without an executed return normally gives undefined. If you try to add undefined to a number, the result becomes NaN. Check the return path before blaming the display.
Arrays keep an ordered list
const values = [12, 3, 5]; console.log(values[0]); console.log(values.length); console.log(values[values.length - 1]);
Expected results: 12, 3, 5. There are three items but the indexes are 0, 1 and 2. Index 3 is outside the list and returns undefined. An index is a position, not a permanent product ID.
A const array binding cannot be assigned a completely different array, but its contents can still be mutated: values.push(7) adds a value. Prefer deliberate changes you can explain; const does not freeze the list.
Trace a total with a loop
const practiceCosts = [24, 12, 5];
let total = 0;
for (const cost of practiceCosts) {
total = total + cost;
}
console.log(total);An accumulator starts at zero. After the first iteration it is 24; after the second it is 36; after the third it is 41. A new calculation must start at zero again—keeping the previous total and adding everything again double-counts.
for...of gives each value. A numeric index loop gives you control of positions:
for (let i = 0; i < practiceCosts.length; i++) {
console.log(i, practiceCosts[i]);
}The strict less-than prevents visiting index length. Using <= adds one invalid iteration. Predict the final valid i before running the loop. Later the debugger branch will let you pause at that boundary.
map transforms; filter selects
const doubled = values.map((value) => value * 2); const larger = values.filter((value) => value >= 5);
map returns a new array with one transformed result per item. filter returns a new array containing only matching items. Neither expression above replaces values. Arrow functions are a compact spelling: (value) => value * 2 implicitly returns the expression, while (value) => { return value * 2; } needs an explicit return inside the braces.
When first learning a total, use the loop you can trace. You do not need to compress everything into a clever chain. A short readable function is better than a one-liner you cannot debug.
Bridge data to a visible list
Objects in the next lesson give each product named fields. For now practise with a list of plain names. Put <ul id="practice-list"></ul> in local HTML and link app.js with defer. Study this safe rendering pattern:
const names = ['Notebook', 'Pen'];
const list = document.getElementById('practice-list');
if (list) {
list.replaceChildren();
for (const name of names) {
const row = document.createElement('li');
row.textContent = name;
list.append(row);
}
}Each iteration creates one element and appends it. replaceChildren clears the old rendered list so rerunning the render does not duplicate rows. textContent displays plain text without interpreting it as HTML. A null guard stops a missing container from causing another error; still inspect why your expected element is missing.
Plan the calculator, not just its syntax
Your assessment needs three or more data objects, a visible row per object, an input per row and a live total. Break it into four jobs:
- Keep product data separate from DOM elements.
- Render the rows once, labelling each quantity input and associating it with the correct product.
- On each input event, read the current strings, convert and validate them, and recompute the sum from zero.
- Display the new total with textContent.
For a hand-trace, use two practice rows: price 12 × quantity 2 gives 24; price 3 × quantity 4 gives 12; sum 36. Setting the first quantity to zero should give 12. These are rehearsal values, not an official pricing rule or a complete quest solution.
Practice and diagnosis
Write your own lineCost function and test three calls, including zero. Use a loop to add the returned costs, then render a list of your own names. Predict each loop iteration before checking Console.
If only one row appears, check whether you selected just one element or replaced the container inside each iteration. If rows duplicate, clear the old render before adding the new one. If a total doubles on each change, reset the accumulator. If undefined appears, inspect bounds and return values.
Before assessment, demonstrate that each array entry is rendered, zero contributes zero, and changing a quantity reruns the calculation without a refresh. Explain which function is called, what it returns and what each loop visits.
Key terms
- Function
- A named, reusable set of steps with inputs and a return value.
- Array
- An ordered list of values, indexed from 0.
- map / filter
- Transform every item / keep matching items.
- for...of
- Loop over each item in a list.
Summary — copy into your notes
- Define once with function, call many times.
- Arrays start at index 0.
- map transforms, filter selects, for...of visits each item.