In JavaScript, a closure is a function to which the variables of the surrounding context are bound by reference.
function getMeAClosure() { var canYouSeeMe = "here I am"; return (function theClosure() { return {canYouSeeIt: canYouSeeMe ? "yes!": "no"}; }); } var closure = getMeAClosure(); closure().canYouSeeIt; //"yes!"
Every JavaScript function forms a closure on creation. In a moment I’ll explain why and walk through the process by which closures are created. Then I’ll address some common misconceptions and finish with some practical applications. But first a brief word from our sponsors: JavaScript closures are brought to you by lexical scope and the VariableEnvironment…
Lexical Scope
The word lexical pertains to words or language. Thus the lexical scope of a function is statically defined by the function’s physical placement within the written source code.
Consider the following example:
var x = "global"; function outer() { var y = "outer"; function inner() { var x = "inner"; } }
Function inner
is physically surrounded by function outer
which in turn is wrapped by the global context. We have formed a lexical hierarchy:
global
outer
inner
The outer lexical scope of any given function is defined by its ancestors in the lexical hierarchy. Accordingly, the outer lexical scope of function inner
comprises the global object and function outer
.
VariableEnvironment
The global object has an associated execution context. Additionally every invocation of a function establishes and enters a new execution context. The execution context is the dynamic counterpart to the static lexical scope. Each execution context defines a VariableEnvironment which is a repository for variables declared by that context. (ES 5 10.4, 10.5)
[Note in EcmaScript 3, the VariableEnvironment of a function was known as the ActivationObject – which is also the term I used in some older articles]
We could represent the VariableEnvironment with pseudo-code…
//variableEnvironment: {x: undefined, etc.}; var x = "global"; //variableEnvironment: {x: "global", etc.}; function outer() { //variableEnvironment: {y: undefined}; var y = "outer"; //variableEnvironment: {y: "outer"}; function inner() { //variableEnvironment: {x: undefined}; var x = "inner"; //variableEnvironment: {x: "inner"}; } }
However, it turns out this is only part of the picture. Each VariableEnvironment will also inherit the VariableEnvironment of its lexical scope. [The hero enters (stage-left)….]
The [[scope]] property
When a given execution context encounters a function definition in the code, a new function object is created with an internal property named [[scope]] (as in lexical scope) which references the current VariableEnvironment. (ES 5 13.0-2)
Every function gets a [[scope]] property, and when the function is invoked the value of the scope property is assigned to the outer lexical environment reference (or outerLex) property of its VariableEnvironment. (ES 5 10.4.3.5-7) In this way, each VariableEnvironment inherits from the VariableEnvironment of its lexical parent. This scope chaining runs the length of the lexical hierarchy starting from the global object.
Let’s see how our pseudo-code looks now:
//VariableEnvironment: {x: undefined, etc.}; var x = "global"; //VariableEnvironment: {x: "global", etc.}; function outer() { //VariableEnvironment: {y: undefined, outerLex: {x: "global", etc.}}; var y = "outer"; //VariableEnvironment: {y: "outer", outerLex: {x: "global", etc.}}; function inner() { //VariableEnvironment: {x: undefined, outerLex: {y: "outer", outerLex: {x:"global", etc.}}; var x = "inner"; //VariableEnvironment: {x: "inner", outerLex: {y: "outer", outerLex: {x:"global", etc.}}; } }
So there we have it – closures are nothing but an unavoidable side-effect of lexical scoping 😉
Dispelling the Myths
Now that we know how closures work, we can begin to address some of the more scurrilous rumors associated with them.
Myth 1. Closures are created only after an inner function has been returned
When the function is created, it is assigned a [[scope]] property which references the variables of the outer lexical scope and prevents them from being garbage collected. Therefore the closure is formed on function creation
There is no requirement that a function should be returned before it becomes a closure. Here’s a closure that works without returning a function:
var callLater = function(fn, args, context) { setTimeout(function(){fn.apply(context, args)}, 2000); } callLater(alert,['hello']);
Myth 2. The values of outer variables get copied or “baked in” to the closure
As we’ve seen, the closure references variables not values.
//Bad Example //Create an array of functions that add 1,2 and 3 respectively var createAdders = function() { var fns = []; for (var i=1; i<4; i++) { fns[i] = (function(n) { return i+n; }); } return fns; } var adders = createAdders(); adders[1](7); //11 ?? adders[2](7); //11 ?? adders[3](7); //11 ??
All three adder functions point to the same variable i
. By the time any of these functions is invoked, the value of i
is 4.
One solution is to pass each argument via a self invoking function. Since every function invocation takes place in a unique execution context, we guarantee the uniqueness of the argument variable across successive invocations.
//Good Example //Create an array of functions that add 1,2 and 3 respectively var createAdders = function() { var fns = []; for (var i=1; i<4; i++) { (function(i) { fns[i] = (function(n) { return i+n; }); })(i) } return fns; } var adders = createAdders(); adders[1](7); //8 (-: adders[2](7); //9 (-: adders[3](7); //10 (-:
Myth 3. Closures only apply to inner functions
Admittedly closures created by outer functions are not interesting because the [[scope]] property only references the global scope, which is universally visible in any case. Nevertheless its important to note that the closure creation process is identical for every function, and every function creates a closure.
Myth 4. Closures only apply to anonymous functions
I’ve seen this claim in one too many articles. Enough said 😉
Myth 5. Closures cause memory leaks
Closures do not of themselves create circular references. In our original example, function inner
references outer variables via its [[scope]] property, but neither the referenced variables or function outer
references function inner
or its local variables.
Older versions of IE are notorious for memory leaks and these usually get blamed on closures. A typical culprit is a DOM element referenced by a function, while an attribute of that same DOM element references another object in the same lexical scope as the function. Between IE6 and IE8 these circular references have been mostly tamed.
Practical Applications
Function templates
Sometimes we want to define multiple versions of a function, each one conforming to a blueprint but modified by supplied arguments. For example, we can create a standard set of functions for converting units of measures:
function makeConverter(toUnit, factor, offset) { offset = offset || 0; return function(input) { return [((offset+input)*factor).toFixed(2), toUnit].join(" "); } } var milesToKm = makeConverter('km',1.60936); var poundsToKg = makeConverter('kg',0.45460); var farenheitToCelsius = makeConverter('degrees C',0.5556, -32); milesToKm(10); //"16.09 km" poundsToKg(2.5); //"1.14 kg" farenheitToCelsius(98); //"36.67 degrees C"
If, like me, you’re into functional abstraction the next logical step would be to currify this process (see below).
Functional JavaScript
Aside from the fact that JavaScript functions are first class objects, functional JavaScript’s other best friend is closures.
The typical implementations of bind, curry, partial and compose all rely on closures to provide the new function with a reference to the original function and arguments.
For example, here’s curry:
Function.prototype.curry = function() { if (arguments.length<1) { return this; //nothing to curry with - return function } var __method = this; var args = toArray(arguments); return function() { return __method.apply(this, args.concat([].slice.apply(null, arguments))); } }
And here’s our previous example re-done using curry
function converter(toUnit, factor, offset, input) { offset = offset || 0; return [((offset+input)*factor).toFixed(2), toUnit].join(" "); } var milesToKm = converter.curry('km',1.60936,undefined); var poundsToKg = converter.curry('kg',0.45460,undefined); var farenheitToCelsius = converter.curry('degrees C',0.5556, -32); milesToKm(10); //"16.09 km" poundsToKg(2.5); //"1.14 kg" farenheitToCelsius(98); //"36.67 degrees C"
There are plenty of other nifty function modifiers that use closures. This little gem comes courtesy of Oliver Steele
/** * Returns a function that takes an object, and returns the value of its 'name' property */ var pluck = function(name) { return function(object) { return object[name]; } } var getLength = pluck('length'); getLength("SF Giants are going to the World Series!"); //40
The module pattern
This well known technique uses a closure to maintain a private, exclusive reference to a variable of the outer scope. Here I’m using the module pattern to make a “guess the number” game. Note that in this example, the closure (guess
) has exclusive access to the secretNumber
variable, while the responses
object references a copy of the variable’s value at the time of creation.
var secretNumberGame = function() { var secretNumber = 21; return { responses: { true: "You are correct! Answer is " + secretNumber, lower: "Too high!", higher: "Too low!" }, guess: function(guess) { var key = (guess == secretNumber) || (guess < secretNumber ? "higher": "lower"); alert(this.responses[key]) } } } var game = secretNumberGame(); game.guess(45); //"Too high!" game.guess(18); //"Too low!" game.guess(21); //"You are correct! Answer is 21"
Wrap up
In programming terms, closures represent the height of grace and sophistication. They make code more compact, readable and beautiful and promote functional re-use. Knowing how and why closures work eliminates the uncertainty around their usage. I hope this article helps in that regard. Please feel free to comment with questions, thoughts or concerns.
Further Reading
ECMA-262 5th Edition
10.4 Creating the VariableEnvironment
10.4.3.5-7 Referencing the [[scope]] property in the VariableEnvironment
10.5 Populating the VariableEnvironment
13.0-2 Assigning the [[scope]] property when a function is created
Very nice explanation of closures. I am particularly fond of closures and use them regularly in my code.
Thanks Rob – me too.
>>The closure is created in two stages
Formally, a closure (a combination of a function code and the parent lexical environment, i.e. that exactly a function object is) is formed at the function’s creation. The function then may never be called in future, but the parent environment is already saved, already closured, i.e. it isn’t garbage collected.
I.e. when an inner function is returned, it already (theoretically, and practically in some implementations, e.g. Rhino) may access closured data without any execution:
And what is formed at activation of
foo
is already its own environment, which may access the parent (closured) environment. At this stage only a correct structure is formed (with saving outer reference in the own environment) in order to access the parent’s data. But the fact of the closure is made at creation.>>Admittedly closures created by outer functions are not interesting because the [[scope]] property only references the global scope, which is universally visible in any case.
Such global functions are interesting from the demonstrating of the again lexical scope (that exactly a requirement for closures) . You may show, that a normal global function is also a closure, since it uses lexically saved (but not dynamically formed, i.e. the environment of a caller) environment in the identifier resolution:
This example relates for “downward funarg problem”, when a function is passed a an argument (as a “funarg”). And this is the one of the reasons why closures where created — to distinguish a dynamic scope from the static (lexical) one.
>>The solution is to pass each argument via a self invoking function
You may want to notice, that this is just a one of the solutions. At least there are 4-5 alternative solutions: while, saving as properties of objects, Mozilla’s let, etc (some even without forming an additional object in the scope chain).
Dmitry.
P.S.: It’s good that you already use the new terminology of environments (actually, the general concept from the common theory).
In addition — Chapter 6. Closures.
Nice input Dmitry. Also I am relieved that you are generally in agreement with my article 😉 (Most of what I wrote about closures is contrary to the literature I have read – so your endorsement of my general approach is important to me)
@Angus Croll, When fn object is created [[scope]] property will be added in scope chain. Also when fn is invoked activation object with fn agrs, & local variables will be added in scope chain.
As per explanation of Nicholas Zakas , activation object has high priority as compared to lexical scope property for property lookup.
In above example funArg() is called in context of window object and it returns window.x value which is 10. That is quite obvious…
Correct me if I understood wrong ??
Superb article Angus, and very good input from Dmitry as well. Really helped solidify my understanding of closures – I didn’t know about internal [[Scope]] property until now. Thank you!
As always, a nice article with a refreshing point of view. I would like highlight the following paragraph
There are many places where this idea isn’t so clearly expressed.
@joseanpg @Chris
Thanks glad you liked it!
allright, about the closures, how this get resolved:
So, to resolve the private member access to public, i did the follow, but the closure wont let me work nicely in public access. How to workaround that?
Sorry for the bad english
On the other hand, may perhaps be interesting to consider this version of ChargeUp. Your asynchronous loop has no body:
I have tried homogenize the methods:
@Mike @Jose
I like the way Jose’s returns thisThunder object referencing public functions. Clean.
More on this later…I need to study the code – (sorry been really busy)
There is an error in fires. Here is the correction
As fires also is a public method , the code below is also valid
@joseanpg This is great – you tidied up Mike’s original code big time
chargeUp doesn’t appear to actually make base energy grow (as you pointed out)
Also why do we want recharge to fail if there is no energy left?
Finally I think recharge can be self invoking – doesn’t need a timeout to invoke
or just do this (I think its cleaner)
@Angus Croll
the
chargeUp
method is to reload the thunderbolt. So, the last time that it fires, thechargeUp
return that it’s empty.@joseanpg
I prefer your first correction in the
chargeUp
method for the default assignment. It really doesn’t need the var statement and it’s better to come after the checks. I will stick with that. I really liked the way to declare functions and make it public in the object literal. thanks.I did this just to test the closures, and now i think it’s a little senseless.
I really like the improvements in the code.
And just after I commented here, I found out that
this
is bound to the object in a object literal statement. But i didn’t knew if it’s the way it is specified.Now i saw the joseanpg’s code, i’m more confident that is the right way. (jsLint also does not complain about that).
i think the anonimous function is more elegant in the asynchronous loop.
But the Angus’ loop actualy does count right and i will stick with that.
joseanpg’s and mine’s, counts 41 secs instead of 40. (we could change the logic statement
( loadTime >= 0)
to( loadTime > 1)
, but it will impossible tochargeUp
instantly.)Thank you all for the tips. It’s very difficult to find people who knows javascript as a real programming Language. i’m very glad i found this blog. =]
My only doubt remaining is about the private method accessing the public attribute. I still think that may exist a better way to do this.
Thanks again. Sorry for the bad english.
Understanding javascript closures.. Keen 🙂
The curry function has a error
return __method.apply(this, args.concat([].slice.apply(arguments)));
I found this too. I was going crazy trying to figure out what I was missing. Aside from that, this is a very helpful article.
Reblogged this on Tech Genius Blog and commented:
Understanding Closures in Javascript
This is simply the best coverage on closures, clears all sorts of confusions regarding them. Thanks for sharing.
nice article..
The guess game has an error though !
var key = (guess==secret) || (guess<secret ? "lower":"higher");
because the conditional operator returns the first value if the condition holds true and returns the value after the colon if the condition is false 🙂
Simply brilliant!
Thanks for explanation of internal working of functions in JS.
Hi Angus,
Thank you for a detailed explanation on closures.I have just started with javascript and find your blog quite useful.
I have a doubt and was hoping you could help me with it.
In the GOOD Example in MYTH 2 you have used (i) at the end of the for loop. can you please explain why is (i) used there? what purpose does it serve?
Very helpful. Thanks!
Thank you very much for this great post! Particularly section myth2 saved my day! Thanks
var callLater = function(fn, args, context) {
// args is accessible via closure to the anonymous function that is called when timeout is triggered.
// context is undefined within the anonymous function so I don’t know why it was included
// in argument list.
// Original sample used the commented out setTimeout code and I don’t know why they used
// apply since context is undefined.
// setTimeout(function(){fn.apply(context, args)}, 2000);
// This seems to work just as well.
setTimeout(function(){fn(args)}, 2000);
}
callLater(alert,[‘hello’]);
Very good article, however I prefer OOP approach far more than closures, which produce bunch of copies of the same function that differs only in parameter (outer, not direct argument). In my opinion it violates the notion of what function actually is. Here’s how I would write a converter example:
function Converter(unit, factor, offset) {
this.unit = unit;
this.factor = factor;
this.offset = offset || 0;
}
Converter.prototype = {
calculate: function(v) {
return [((this.offset + v) * this.factor).toFixed(2), this.unit].join(‘ ‘);
}
};
var milesToKm = new Converter(‘km’, 1.60936);
var poundsToKg = new Converter(‘kg’,0.45460);
var farenheitToCelsius = new Converter(‘degrees C’,0.5556, -32);
console.log(milesToKm.calculate(10));
console.log(poundsToKg.calculate(2.5));
console.log(farenheitToCelsius.calculate(98));
I believe it’s more readable, testable, reusable, maintanable. One may say: ok, you are not duplicating the functions, but instead create the same number of objects. That’s correct, but I copy the data (which are different for each object) and not functionality (which is same for all objects).
Very good article, however I prefer OOP approach far more than closures, which produce bunch of copies of the same function that differs only in parameter (outer, not direct argument). In my opinion it violates the notion of what function actually is. Here’s how I would write a converter example:
function Converter(unit, factor, offset) {
this.unit = unit;
this.factor = factor;
this.offset = offset || 0;
}
Converter.prototype = {
calculate: function(v) {
return [((this.offset + v) * this.factor).toFixed(2), this.unit].join(‘ ‘);
}
};
var milesToKm = new Converter(‘km’, 1.60936);
var poundsToKg = new Converter(‘kg’,0.45460);
var farenheitToCelsius = new Converter(‘degrees C’,0.5556, -32);
console.log(milesToKm.calculate(10));
console.log(poundsToKg.calculate(2.5));
console.log(farenheitToCelsius.calculate(98));
I believe it’s more readable, testable, reusable, maintanable. One may say ok, you are not duplicating the functions but instead create the same number of objects. That’s correct but I copy the data (which is different for each object) and not functionality (which is same for all objects).
Very detailed article…
hey in ur explained each execution context has variable environment.But in your sample code you write 2 environentvarable
function outer() {
1=> //VariableEnvironment: {y: undefined, outerLex: {x: “global”, etc.}};
var y = “outer”;
1=>2 //VariableEnvironment: {y: “outer”, outerLex: {x: “global”, etc.}};.Why is that