Before this lesson
Understand variables, conditions and loops, and recognize function calls.
What you will be able to do
Extract repeated logic into testable functions and use closures for isolated state.
Understand the mechanism
Parameters are inputs and return provides output; without a return value, a function yields undefined. Prefer predictable calculation functions and keep DOM and storage effects at boundaries. Rules can then be tested through inputs and outputs.
let and const have block scope. Functions access outer variables according to where they were defined: lexical scope. A closure retains access to an environment, not a frozen snapshot. Each factory call creates a separate local environment for independent component state.
Arrow functions capture surrounding this; ordinary functions depend on how they are called. Do not replace methods with arrows only to shorten syntax. A finished synchronous try cannot catch later asynchronous callback failures; handle awaited failures where they occur.
Runnable example
function makeCounter(start = 0) {
let value = start;
return {
increment() { value += 1; return value; },
read() { return value; }
};
}
const a = makeCounter();
const b = makeCounter(10);
console.log(a.increment(), a.increment(), b.read());
Trace and verify
Expect 1, 2 and 10. Each factory call creates a new environment. Outside code cannot directly read local value, but returned methods can. Remove return from increment to observe undefined despite the state changing.
Common mistakes and boundaries
Closures can retain large objects. Remove listeners and timers that are no longer needed. Recursion requires a base case and is unsuitable for unbounded depth. Hoisting should not hide unclear initialization order.
Practice challenge
Add reset that restores the initial start value; verify resetting a does not change b.
Reference solution and reasoning
start belongs to the same invocation environment. reset updates only that instance and can return the new value for immediate rendering.
// Add this method to the returned object:
// reset() { value = start; return value; }