As you learned in my post on Scope, Namespaces, “use strict”, all variables are accessible from the global scope except variables that are declared within a function using the
var
keyword. In this post, we add the idea of closures.
Closures are functions that retain a reference to their free variables.
And we show how you can use closures in building a robust revealing module pattern. Along the way, we explore some other patterns, such as the self-invoking anonymous function. And in the conclusion show how you can use the revealing module pattern to extend existing modules.
This post relies heavily on Joe Zim’s article JavaScript Closures and the Module Pattern, whose explanation dovetails with the revealing module pattern and asynchronous modules definition.
When you see Asynchronous Module Definition (AMD), you will see how asynchronous modules build on these concepts.
Scope
Let’s start with scope.
All variables are accessible from the global scope except variables that are declared within a function using the var
keyword.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
variable1 = 1; // Global Scope | |
var variable2 = 2; // Not within a function: Global Scope | |
function funcName() { | |
variable3 = 3; // No var keyword: Global Scope | |
var variable4 = 4; // Local Scope only | |
} |
Within a function, you also have access to the global scope and every other scope above the function that you are in. In other words an inner function has access to the variables that are within the function that wraps it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var globalvar = 1; // Global Scope | |
function outer() { | |
var outervar = 2; // Scope is within outer() | |
function inner() { | |
var innervar = 3; // Scope is within inner() | |
console.log(globalvar); // => 1 | |
console.log(outervar); // => 2 | |
console.log(innervar); // => 3 | |
} | |
console.log(globalvar); // => 1 | |
console.log(outervar); // => 2 | |
console.log(innervar); // => Reference Error; | |
} | |
console.log(globalvar); // => 1 | |
console.log(outervar); // => Reference Error | |
console.log(innervar); // => Reference Error |
Self-Invoking Anonymous Function (SIAF)
Scope is useful when you want to prevent anyone a chance to override any of your code without your permission. And you can use an anonymous function (no name is given to it and it is not assigned to a variable) that immediately executes itself. This is commonly known as a Self-Invoking Anonymous Function (SIAF), though it is probably more accurately referred to as an Immediately Invoked Function Expression (IIFE – pronounced “iffy”) by Ben Alman.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
// This function immediately runs and all variables within here are private | |
}()); |
Right after the closing curly brace, just put an opening and closing parenthesis and the function will immediately be executed. The parentheses around the entire function expression aren’t necessary for the code to run, but are generally used as a signal to other developers that this is an IIFE, not a standard function. Some people like to prefix with an exclamation point (!) or a semicolon (;), rather than wrapping the whole thing in parentheses.
Closure
Closures are functions that retain a reference to their free variables.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function f(x) { | |
function g() { | |
return x; | |
} | |
console.log(g()); | |
} | |
f(5); |
It’s no surprise that when you call f
with the argument 5
, when g
is called it has access to that argument. What’s a bit more surprising is that if you return g
from the argument, the returned function still has access to the argument 5
(as shown in the original example). The bit that can be a bit mind-blowing (and I think generally the reason that people have such trouble understanding closures) is that the returned g
actually is remembering the variable x
that was defined when f
was called.
Using Closure in a Module
By returning an object or variable and assigning it to a variable outside of the function, we can expose whatever we wish to the outside world, so we can have both public and private methods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Module = (function() { | |
// Following function is private, but can be accessed by the public functions | |
function privateFunc() { … }; | |
// Return an object that is assigned to Module | |
return { | |
publicFunc: function() { | |
privateFunc(); // publicFunc has direct access to privateFunc | |
} | |
}; | |
}()); |
You can also use the arguments to send in and shrink the name of commonly used assets:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Module = (function($, w, undefined) { | |
// … | |
// return {…}; | |
}(jQuery, window)); |
In this case, sent in jQuery
and window
, which were abbreviated to $
and w
, respectively. Notice that I didn’t send anything in for the third argument. This way undefined
will be undefined, so it works perfectly. Some people do this with undefined
because for whatever reason it is editable. So if you check to see if something is undefined
, but undefined
has been changed, your comparison will not work. This technique ensures that it will work as expected.
How to Recognize Closures
- Whenever you use
function
inside another function, a closure is used. - Whenever you use
eval()
inside a function, a closure is used. The text youeval
can reference local variables of the function, and withineval
you can even create new local variables by usingeval('var foo = …')
- When you use
new Function(…)
(the Function constructor) inside a function, it does not create a closure. (The new function cannot reference the local variables of the outer function.) - A closure in JavaScript is like keeping a copy of all the local variables, just as they were when a function exited.
- It is probably best to think that a closure is always created just on entry to a function, and the local variables are added to that closure.
- A new set of local variables is kept every time a function with a closure is called (given that the function contains a function declaration inside it, and a reference to that inside function is either returned or an external reference is kept for it in some way).
- Two functions might look like they have the same source text, but have completely different behaviour because of their ‘hidden’ closure. I don’t think JavaScript code can actually find out if a function reference has a closure or not.
- If you are trying to do any dynamic source code modifications (for example:
myFunction = Function(myFunction.toString().replace(/Hello/,'Hola'));
), it won’t work ifmyFunction
is a closure (of course, you would never even think of doing source code string substitution at runtime, but…). - It is possible to get function declarations within function declarations within functions — and you can get closures at more than one level.
- I think normally a closure is the term for both the function along with the variables that are captured. Note that I do not use that definition in this article!
- I suspect that closures in JavaScript differ from those normally found in functional languages.
Revealing Module Pattern
The revealing module pattern is another way to write the module pattern that takes a bit more code, but is easier to understand and read sometimes. Instead of defining all of the private methods inside the IIFE and the public methods within the returned object, you write all methods within the IIFE and just “reveal” which ones you wish to make public within the return
statement.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Module = (function() { | |
// All functions now have direct access to each other | |
var privateFunc = function() { | |
publicFunc1(); | |
}; | |
var publicFunc1 = function() { | |
publicFunc2(); | |
}; | |
var publicFunc2 = function() { | |
privateFunc(); | |
}; | |
// Return the object that is assigned to Module | |
return { | |
publicFunc1: publicFunc1, | |
publicFunc2: publicFunc2 | |
}; | |
}()); |
There are a few advantages to the revealing module pattern versus the normal module pattern:
- All the functions are declared and implemented in the same place, thus creating less confusion.
- Private functions now have access to public functions if they need to.
- When a public function needs to call another public function they can call
publicFunc2()
rather thanthis.publicFunc2()
, which saves a few characters and saves your butt ifthis
ends up being something different than originally intended.
The only real downside to the revealing module pattern, as I said, is that you have to write a bit more code because you have to write the function and then write its name again in the return
statement, though it could end up saving you code because you can skip the this.
part.
Extending Revealing Module Pattern
You can use the module pattern for extending already-existing modules. You use this technique to create plugins to libraries like jQuery.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($) { | |
$.pluginFunc = function() { | |
… | |
} | |
}(jQuery)); |
This code is pretty flexible because you don’t even need the var jQuery =
or the return
statement near the end. jQuery will still be extended with the new method without them. It’s actually probably bad for performance to return the entire jQuery object and assign it, however, if you want to assign jQuery to a new variable name at the same time that you’re extending it, you can just change jQuery
on the first line to whatever you want.
References
How do JavaScript closures work?
Closures explained with JavaScript
JavaScript Closures for Dummies