A function keeps access to the variables of the scope it was created in, even after that scope has finished. That is a closure. makeCounter() declares let count = 0 and returns a function that increments it; each call of makeCounter creates a fresh count, and the returned function is the only thing that can touch it. That is how JavaScript does private state without classes.
Closures explain a lot of everyday code: event handlers that remember which button they belong to, setTimeout callbacks that still see local variables, and function factories from the previous lesson.
function makeGreeter(greeting) {
return (name) => `${greeting}, ${name}`;
}
const hi = makeGreeter("Hi");
console.log(hi("Ada")); // Hi, AdaYour task
Write makeCounter() returning an object with increment() (adds one and returns the new count), decrement(), and value(), all sharing one private count that starts at 0. Then write once(fn) returning a function that calls fn the first time and returns that first result on every later call without calling fn again. Finally, makeDiscount(rate) returning a function that takes an amount and returns it with the rate taken off, rounded to two decimals: makeDiscount(0.1)(50) is 45.
Part of the final project. makeDiscount builds the function that applies an order's coupon rate. It is saved in this browser and loaded into Project: checkout when you get there.
Hint 1
return { increment: () => ++count, decrement: () => --count, value: () => count };
Hint 2
once: let called = false; let result; return (...args) => { if (!called) { called = true; result = fn(...args); } return result; }. makeDiscount: return (amount) => Math.round(amount * (1 - rate) * 100) / 100;
Show the solution
function makeCounter() {
let count = 0;
return {
increment: () => ++count,
decrement: () => --count,
value: () => count,
};
}
function once(fn) {
let called = false;
let result;
return (...args) => {
if (!called) {
called = true;
result = fn(...args);
}
return result;
};
}
function makeDiscount(rate) {
return (amount) => Math.round(amount * (1 - rate) * 100) / 100;
}