liveBook · Manning

Scope

As explained in Secrets of the JavaScript Ninja, Second Edition

The region in which an identifier's binding is visible and can be resolved.

A click counter needs to remember its count without letting unrelated code change it. Scope determines where a variable is visible: calling a JavaScript function creates a scope whose local variables are not visible outside that function. section 11.1.1

Scope also makes closures useful. A function can keep access to variables that were in scope when it was created, even after the surrounding function finishes. That is why a click handler can continue updating a local count. Execution contexts and lexical environments help explain this behavior under the hood. section 5.6 section 11.1.1

Listing 11.1. The module pattern
const MouseCounterModule = function() {                         #A
  let numClicks = 0;                                            #B
  const handleClick = () => {                                   #C
    alert(++numClicks);                                         #C
  };                                                            #C
  
  return {                                                      #D
    countClicks: () => {                                        #D
      document.addEventListener("click", handleClick);          #D
    }                                                           #D
  };                                                            #D
}();

assert(typeof MouseCounterModule.countClicks === "function",    #E
       "We can access module functionality");                   #E
assert(typeof MouseCounterModule.numClicks === "undefined"      #F
    && typeof MouseCounterModule.handleClick === "undefined" ,  #F
       "We cannot access internal module details");             #F

The module-pattern listing puts the count inside a function scope and returns an object with a public method. The method can use the hidden state through a closure; outside code cannot read the count directly. section 11.1.1

Keep separate function scopes in mind when extending a module: methods added in another function do not gain access to the first function’s local variables. Historically, JavaScript relied on global and function-level variables; block-level variables are a more recent addition. section 11.1.1 section 1.1

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Explains function-created scope through a module example and links closures to execution contexts and lexical environments, without specifying identifier lookup order.
Examples
Uses a browser click counter and a module-pattern listing with a hidden count and public method.
What it assumes
Assumes familiarity with JavaScript functions and callbacks while explaining the visibility created by calling a function.
What you can do after
Build it from scratch: use function scope and closures to expose a module interface while keeping state inaccessible from outside.
How it connects
Connects scope to functions, closures, callbacks, lexical environments, execution contexts, and the module pattern.

Also explained in

Compare how 21 books explain scope →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.