Overview

7 Functions for the master: closures and scopes

JavaScript closures are the mechanism that lets a function keep access to the variables and other functions that were in scope when it was defined, even if it runs much later or in a different place. This makes many everyday patterns possible, especially callbacks for events, timers, and animations, because the function can still “see” its surrounding data after the original scope has finished. Closures behave like a protective bubble around a function and its lexical environment, keeping those values alive as long as the function itself remains reachable.

The chapter then connects closures to the broader rules of scope. It explains that JavaScript scopes are created not only by functions, but also by modules and block structures such as if, for, and switch, with let and const following block scope while var is limited to the nearest function or module. It also shows how loop scoping works with closures, why let gives the expected per-iteration values in timer callbacks, and how execution order matters: variables can be in scope before they are initialized, leading to the Temporal Dead Zone, while function declarations are hoisted and can be used earlier than their appearance in code.

Finally, the text examines the global scope and the scope chain, showing how JavaScript resolves names by searching outward from the local scope to the global object, and how globalThis provides a consistent way to reach that object across environments. It also warns that closures can have memory costs, because engines may keep scope data alive longer than necessary when a function survives, potentially causing leaks with large objects captured indirectly. The practical takeaway is to understand scope and hoisting well, use modern declaration styles, prefer explicit initialization and cleanup, and be mindful that closures are powerful but not free.

Like a protective bubble, the closure for innerFunction keeps the variables in the function’s scope alive for as long as the function exists.

Summary

  • Closures are a built-in feature of all JavaScript functions that allow a function to access all variables that are in scope when the function itself was defined. They create a “safety bubble” of the function and the variables that are in scope at the point of the function’s definition. This way, the function has all it needs to execute, even if the scope in which the function was created is long gone.
  • Any block of code with { and } defines a new scope, unless that block is an object literal.
    • Variables defined in a for loop initializer are considered to be in the same scope as the loop body, and each iteration has its own scope.
  • The let and const keywords define a variable in the closest scope, as do keywords like function and class. The older var keyword has its own scoping rules, but most JavaScript developers prefer not to use it.
  • A variable can’t be referenced until its declaration has been executed, with the exception of function declarations and imports, which are “hoisted” to the top of their scope.
  • The global scope in JavaScript contains the properties of an object called globalThis. You can declare global variables by attaching them to that global object.
  • JavaScript engines may sometimes avoid garbage collecting variables in a scope with live closures, which can lead to memory leaks.

FAQ

What is a closure in JavaScript?A closure is a function together with the variables in its surrounding lexical scope that were in scope when the function was defined. It lets the function keep accessing those variables even after the outer scope has finished executing.
Why are closures important in JavaScript?Closures are essential for many common patterns, especially callbacks, event handlers, timers, animations, and memoization. They let functions retain access to state without putting that state on the global object.
How does a closure keep variables “alive” after a function returns?When a function is created inside another scope, JavaScript creates a closure that preserves access to that scope. As long as the function reference still exists, the engine keeps the referenced variables from being garbage-collected.
How do closures work with nested functions?An inner function can access variables from its own scope, its parent scope, and any outer scopes. If that inner function is returned or stored elsewhere, it still keeps access to those original variables through its closure.
What is the relationship between scope and closure?Closure is a result of scope. A scope defines where variables are visible, and a closure preserves access to the variables that were visible when a function was defined.
What kinds of scopes exist in JavaScript?JavaScript has function scope, module scope, and block scope. Blocks created by constructs like for, if, switch, or standalone curly braces can create new scopes as well.
How does let behave differently from var in loops?let is block-scoped, so each loop iteration gets its own binding. That means closures created inside the loop see the value from the specific iteration they were created in. var is function-scoped, so all callbacks would share the same variable.
What is hoisting in JavaScript?Hoisting is JavaScript’s behavior of treating function declarations as if they were declared at the top of their scope. This means a function declaration can be called before its textual location in the code.
Why does const x = 1; cause a different error than an undeclared variable?Because variables in scope but not yet initialized are in the Temporal Dead Zone. Referencing them before initialization throws ReferenceError: Cannot access 'x' before initialization, whereas a truly undeclared variable would produce x is not defined.
How can closures contribute to memory leaks?If a closure keeps a scope alive, objects in that scope may remain in memory longer than expected. Sometimes JavaScript engines are conservative and keep large objects alive even when they are no longer needed, so it’s important to release large resources explicitly when possible.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secrets of the JavaScript Ninja, Third Edition ebook for free