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; }

Further reading