Understanding JavaScript Closures and Scope

JavaScript Closures and Scope

This is going to be my attempt on trying to explain JavaScript scope and closures in the most basic and intuitive way. Scope refers to where variables and functions are accessible, and in what context they are being executed. You can think of scope as a current location and access to variables, so without any functions, variables belong to the global scope and are stored in the window object (everyone can access it – the top-level execution context). Inside a function, variables defined using the var keyword are “boxed in” and running within the function scope (or local scope): contained within the function and cannot be accessed from a higher level scope (ie. global window object). Inside the function, the JavaScript interpreter searches for the most local variable it can find, and uses that one. If it can’t find it inside a function, it looks outside in the global scope as any variable defined in the global scope is available to everything. Consider this example:

As you can see, JavaScript has Local Scope and Global Scope and variables defined with the var keyword inside of a function belong to the Local Scope and cannot be accessed outside of a function. However, inside the function, JavaScript has access to the Global Scope and any other Local Scope within the function that wraps it (nested functions). Before we dig into nested functions, let’s define a JavaScript function as a “subprogram” which can accept values (arguments passed to functions), change them internally, and return values.

Functions in JavaScript are first-class objects (Function objects), which means that they can be manipulated and passed around just like any other object. This also means that they can be passed around in variables, they can accept functions as arguments and they can return functions. JavaScript functions can also be anonymous functions (lambdas, function literal, or functions without a name) and they can have nested functions. Let’s consider a simple example of a nested function below, a function that has another function inside.

As you can see above, the inner function is physically surrounded by the outer function which in turn is wrapped by the global context. Each of these functions establishes a new execution context or scope (there is a difference in meaning of these terms but it’s not important right now). So, when f() is invoked, variable z gets a value and when inner g(2) function gets invoked, it accepts the 2 for y and tries to find a variable z inside itself (innermost scope), but doesn’t find z and looks at the parent scope (outer function f()) and finds z and executes alert(3). If f() didn’t have a variable z declaration, the JavaScript engine would have tried to find variable z in the global scope. This is what happens in the example of g(2) and alert(z) when JavaScript throws and error because it tries to find variable z and function g() in the global scope (they are in the local scope of function f() and not accessible).

I defined a variable x with function f() to show how you can assign functions to variables and this does not call a function, it just assigns a reference. Of course, appending parentheses on x calls the function x() which also alerts 3. The interesting part is that function g() above is a closure and it has its own scope (not local and not global) where it keeps the variable definition of z. If you look at firebug or web developer toolbar you will see that when the alert occurs, there is a Closure container under Scope Variables where 1 is assigned to z. Closures have three objects in their scope chain: the closure variables, the local variables, and the global variables. Here are another 2 examples of JavaScript Closures:

I have added the variable z declaration to global scope just to highlight the power of Closures as both these examples alert(3) and the function g() is not grabbing variable z from the global scope as it already has it in its own scope. JavaScript uses lexical scoping and lexical scope means functions are executed using the variable scope in effect when the function was defined. So, lexical scoping and the ability to make nested functions in JavaScript enables closures. A closure is created when an inner function accesses variables from the outer function. JavaScript basically saves the state of the local outer variables in a separate “closure” object. A closure function captures its execution environment, it has related scope in which the function’s variables are resolved.

If you are writing code where inner functions refer to local variables of the outer function, than you are creating closures. To be more precise, any function definition in JavaScript always creates a closure but if the function is in the Global Scope, then only the Global Scope is referenced in the closure and thus, this case is generally ignored when discussing closures. It does come up, however, when we consider when Closures are created. When any function is created in JavaScript, it gets a “scope” property which references the variables of the outer lexical scope and prevents them from being garbage collected. So, closure is created as a result of lexical scoping in JavaScript and it is created on any function creation (in nested functions, a closure is created when the outer function exits so the values of any variables will be saved as they are when the outer function exits). It does not need to be returned before it becomes a closure, however this makes most sense when using closures. Consider this example:

The inner function still remembers that z is 1 even when it gets executed from another function. As John Resig’s points out in his “Secrets of a JavaScript Ninja” book, “closures allow a function to access all the variables, as well as other functions, that are in scope when the function itself is declared”, so even after the outer function has finished executing, the inner function still has access to the original scope in which it was declared through its closure. In other words, the inner function still has access to the outer function’s variables after the outer function has returned.

Basically closures retain a private variable state and they are great for passing state around in your application. They can save us from the need to create global variables and help you conceal your code from the public eye. Closures are also good for emulating private methods in JavaScript. They are often used for events or objects that return a single method. They allow you to work with curried JavaScript functions (a functional programming technique) and the Module pattern (flexible way to do namespaces in JavaScript). These are more advanced topics that I might cover later on but for now, the links below can shed more light on these JavaScript patterns, closures, scope and much more:

Closure definition on WikiPedia
JavaScript Execution Context and Closure
Grokking V8 Closures
javaScript Scope and Closures
Closures and the Module Pattern
Closures – Mozilla
JS Closures
Introduction to Closures
Closures and Functional Programming
How do Closures work?
Understanding JavaScript Closures
Event Handler persistence with Closures
JavaScript Closures
Use Cases for JavaScript Closures
NetTuts on JavaScript Closures
LexicalEnvironment and Closures
Closures provide encapsulation in Javascript
Strict Mode and Static Scoping
JavaScript Scope Context Coloring
Understanding JavaScript Hoisting

Now, in terms of a basic and intuitive explanation, I think I failed as this post is just too damn long. But, in summery:

JavaScript allows nested functions and as a result of lexical scoping (functions are executed using the variable scope in effect when the function was defined), when inner functions are run they retain all the references to variables that they had when they were created.

External:

Using this responsibly in JavaScript

Facebook Twitter Hacker News Reddit More...
  • Adam

    “I defined a variable x with function z() to show how you can assign functions to variables and this does not call a function, it just assigns a reference.”

    I believe you may have a typo here as I don’t see any function z().

  • Adam

    “I defined a variable x with function z() to show how you can assign functions to variables and this does not call a function, it just assigns a reference.”

    I believe you may have a typo here as I don’t see any function z().

  • Adam

    “I defined a variable x with function z() to show how you can assign functions to variables and this does not call a function, it just assigns a reference.”

    I believe you may have a typo here as I don’t see any function z().

    • iweczek

      Good catch, I have fixed the typo. Thanks.