JavaScript: functions, arrays and objects
Lesson 6 of 8
6JavaScript: functions, arrays and objects
The big pictureIn the last lesson you wrote commands that run once. Now you learn to wrap steps in functions you use many times, and to store real data: a list of orders, a user with their properties. These three, functions, arrays and objects, are 80% of what you will write in React and on the server later.
What the picture shows: A chain of transformations: pick the paid orders, turn each into its amount, then add them up. You will see this style in all modern JavaScript.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
A function is a small machine: you feed it inputs (like a number of cups), it does its job, and it hands you a result (the price). You build it once and use it a thousand times. An array is a row of drawers numbered from zero. An object is an ID card: "name: Noura, city: Riyadh". And array methods are like a factory line: one station removes the faulty items (filter), one wraps each piece (map), and one counts the total (reduce).
Functions are first-class values: stored in variables, passed to other functions (callbacks), and returned from them (closures that remember their scope). Arrow functions are shorter and have no this or arguments of their own. Arrays are ordered, indexed objects, and their non-mutating methods (map, filter, reduce, slice, toSorted) return new values while push, sort and splice change the original. Objects are passed by reference, not value, so two names pointing at the same object change together, which is why you copy with spread {...obj} (shallow) or structuredClone (deep). Destructuring, defaults, ?. and ?? shorten a lot. JSON is a text format for moving data between browser and server, with JSON.stringify and JSON.parse.
Before You Start
⚡JavaScript from zero
You know variables, if and for.
The Core Idea
1Functions: a recipe with a name
A function is defined with function and a name, then parameters in parentheses (its inputs), then a block. return hands back the result and ends the function. You call it by name and give it arguments (the actual values). A parameter can have a default for when none is given.
function price(cups, each = 14) {
return cups * each;
}
function greet(name) {
return `Welcome back, ${name}!`;
}
console.log(price(3)); // uses the default 14
console.log(price(3, 18)); // overrides it
console.log(greet("Lina"));
const result = price(2);
console.log("stored result:", result);return. A function that calculates but returns nothing gives you undefined. function double(n) { n * 2 } then double(4) gives undefined; the right version is return n * 2.2Arrow functions and passing functions
An arrow function is a shorter form: (a, b) => a + b. If its body is a single expression it needs no braces and no return. In JavaScript a function is a value like any other: store it in a variable, pass it to another function to call later. A function passed this way is a callback, and you will see them everywhere: events, timers, array methods.
const withVat = (amount) => Math.round(amount * 1.15);
const isCheap = (price) => price < 15;
console.log(withVat(100), isCheap(12), isCheap(20));
// a function that takes another function
function applyToAll(list, fn) {
const out = [];
for (const item of list) out.push(fn(item));
return out;
}
console.log(applyToAll([10, 20, 30], withVat));
console.log(applyToAll([10, 20, 30], (n) => n / 10));3Arrays: ordered lists
An array is a list in square brackets [ ]. Each item has an index starting at zero: the first is list[0], the last list[list.length - 1] or list.at(-1). push adds to the end, pop removes from the end, includes asks "is it there?", indexOf "where is it?", and slice cuts out a part without changing the original.
const menu = ["espresso", "latte", "mocha"];
console.log(menu[0], menu.at(-1), menu.length);
menu.push("v60");
console.log(menu);
console.log(menu.includes("tea"), menu.indexOf("mocha"));
console.log(menu.slice(1, 3), "| original:", menu.length, "items");
const last = menu.pop();
console.log("removed", last, "->", menu);menu[3] does not exist and gives undefined with no error. The most famous beginner bug is called an "off-by-one error".4filter, map and reduce: think in transformations
Instead of a for loop with temporary variables, describe what you want: filter(fn) picks the items the function returns true for. map(fn) transforms each item into something new and returns an array of the same length. reduce(fn, start) combines the array into one value. Each returns a new value and leaves the original alone. Alongside them: find for the first match, some/every for whether any/all match, and sort for ordering.
const orders = [
{ id: 1, item: "latte", cups: 2, paid: true },
{ id: 2, item: "mocha", cups: 1, paid: false },
{ id: 3, item: "v60", cups: 3, paid: true },
{ id: 4, item: "latte", cups: 1, paid: true },
];
const PRICE = { latte: 14, mocha: 16, v60: 18 };
const paid = orders.filter((o) => o.paid);
const amounts = paid.map((o) => o.cups * PRICE[o.item]);
const revenue = amounts.reduce((sum, x) => sum + x, 0);
console.log("paid ids:", paid.map((o) => o.id));
console.log("amounts:", amounts);
console.log("revenue:", revenue);
console.log("first unpaid:", orders.find((o) => !o.paid).item);
console.log("any big order?", orders.some((o) => o.cups >= 3));How does reduce work step by step? The accumulator sum starts at the second argument (0), then for each item it returns sum + x, which becomes sum for the next item: 0 → 28 → 82 → 96. The last value is the result.
5Objects: a card of properties
An object goes in curly braces { }, holding key: value pairs. You read a property with a dot user.name, or with brackets user["name"] when the key is in a variable. You add or change a property by assigning. A value can be anything: text, a number, an array, another object, or a function (then it is called a method).
const user = {
name: "Noura",
city: "Riyadh",
points: 120,
favourites: ["latte", "v60"],
prefs: { milk: "oat", sugar: false },
greet() {
return `Hi, I am ${this.name}`;
},
};
console.log(user.name, user["city"], user.favourites[1], user.prefs.milk);
user.points += 30;
user.phone = "0500000000";
console.log(user.points, user.phone);
console.log(user.greet());
console.log(Object.keys(user));const a = user; a.city = "Jeddah"; changed user too! Objects are copied by reference: a and user are two names for the same card. For an independent copy write const a = { ...user }.6Destructuring, spread, ?. and ??
Destructuring pulls out what you need from an object or array in one line: const { name, city } = user. Spread ... unpacks an array or object inside another, so you copy with a change without touching the original. ?. reads a property safely, giving undefined instead of crashing if what comes before it is missing. ?? gives a fallback when the value is null or undefined.
const user = { name: "Noura", city: "Riyadh", prefs: { milk: "oat" } };
const { name, city } = user;
const moved = { ...user, city: "Jeddah" };
console.log(name, city, "->", moved.city, "| original still", user.city);
const [first, ...rest] = ["latte", "mocha", "v60"];
console.log(first, rest);
console.log([...rest, "tea"]);
console.log(user.prefs?.milk);
console.log(user.address?.street); // undefined, no crash
console.log(user.address?.street ?? "no address");7JSON: data when it travels
When the server sends data to the browser, or you save something in the browser, objects do not travel as they are but as text in JSON format, which looks like JavaScript objects except the keys are always in double quotes. JSON.stringify(obj) turns an object into text, and JSON.parse(text) turns it back into an object.
const order = { id: 7, items: ["latte", "mocha"], total: 30, paid: true };
const text = JSON.stringify(order);
console.log(typeof text, text);
const back = JSON.parse(text);
console.log(typeof back, back.items[1], back.total + 5);
// what an API usually sends back
const reply = '{"menu":[{"name":"latte","price":14},{"name":"v60","price":18}]}';
const data = JSON.parse(reply);
console.log(data.menu.map((d) => `${d.name}: ${d.price}`).join(", "));Worked example
Problem: the café's sales report for a whole day. From the list of orders: (1) only the paid ones, (2) revenue per drink, (3) the best-selling drink, (4) the customers who ordered more than once. Solution with a small function per question:
const PRICE = { latte: 14, mocha: 16, v60: 18 };
const orders = [
{ customer: "Ali", item: "latte", cups: 2, paid: true },
{ customer: "Sara", item: "v60", cups: 1, paid: true },
{ customer: "Ali", item: "mocha", cups: 1, paid: false },
{ customer: "Lina", item: "latte", cups: 3, paid: true },
{ customer: "Sara", item: "latte", cups: 1, paid: true },
];
const paidOnly = (list) => list.filter((o) => o.paid);
function revenueByDrink(list) {
return list.reduce((acc, o) => {
acc[o.item] = (acc[o.item] ?? 0) + o.cups * PRICE[o.item];
return acc;
}, {});
}
function bestSeller(byDrink) {
return Object.entries(byDrink).sort((a, b) => b[1] - a[1])[0];
}
function repeatCustomers(list) {
const counts = {};
for (const { customer } of list) counts[customer] = (counts[customer] ?? 0) + 1;
return Object.keys(counts).filter((name) => counts[name] > 1);
}
const paid = paidOnly(orders);
const byDrink = revenueByDrink(paid);
console.log("revenue by drink:", byDrink);
console.log("best seller:", bestSeller(byDrink));
console.log("came back:", repeatCustomers(orders));Myth vs Reality
| Myth | Reality |
|---|---|
| A for loop is faster, so always use it. | The difference is unnoticeable in most programs, and map and filter read more clearly with fewer bugs. |
| const makes an object frozen. | It only stops rebinding the variable; the properties inside can change. |
| JSON is JavaScript. | A text format inspired by it, read by every language: Python, Java and others. |
Where you meet it at work
🛍️Shopping carts
The products are an array of objects, and the total is a reduce.
📊Report dashboards
Filtering and grouping sales data before charting it.
🔌Talking to the server
Everything from an API arrives as JSON and you transform it with map.
Test your understanding
Which method returns an array of the same length after transforming each item?
map transforms each item and drops nothing.
const a = [1]; a.push(2); what happens?
const forbids a = ..., not changing the array's contents.
What is ["a", "b", "c"][1]?
Indexes start at zero, so index 1 is the second item.
What does function add(a, b) { a + b } return for add(2, 3)?
Without return the function gives undefined even though it calculated.
How do you copy an object with one property changed without touching the original?
Spread builds a new object; direct assignment points at the same one.
Quick review cards
const { a, b } = obj pulls properties into variables.Check Your Understanding
Why filter then map, not the reverse, in the revenue example?
Because map turns each order into a number and loses the paid property, so you could not filter afterwards.
What is the difference between a parameter and an argument?
The parameter is the name in the function's definition; the argument is the actual value you pass when calling it.
Why did the original object change when you edited its copy?
Because b = a copies the reference, not the object; both point at the same card. Copy with { ...a }.
When do you need JSON.parse?
When you receive JSON text from a server or from storage and want to work with it as an object.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Done with this lesson?
Sign in to save your progress.