Try Tuts+ Premium, Get Cash Back!
Closures: Front to Back

Closures: Front to Back

Tutorial Details
  • Applications Used: JavaScript Closures
  • Difficulty: Intermediate

Closures are often viewed as an arcane art in the land of JavaScript. Once mastered, they allow you to write some truly amazing JavaScript. This article will get you up to speed on the magic of JavaScript closures.


What Is A Closure?

One of the key truths of JavaScript is that everything is an object. This, of course, includes functions.

A closure is nothing more than a function object with a related scope in which the function’s variables are resolved.

Closures get their name because of the way they close over their contents. Consider the following bit of JavaScript:

topping = "anchovi";
function pizzaParty(numSlices) {
	var topping = "pepperoni",

	innerFunction = function() {
		var topping = "ham";
		console.log(" .....But put " + topping + " on " + numSlices + " slices");
	};

	console.log("This pizza is all about the " + topping);

	innerFunction();
}
pizzaParty(3);

If you open up your favorite console and run that bad boy, you will be greeted with a delicious message to the effect of “This pizza is all about the pepperoni ….. But put ham on 3 slices.” This example illustrates some key concepts of JavaScript that are crucial to getting a hold on closures.

A Closure is a Function Object

How many function objects are in the above code? Well… we have our pizzaParty function, and nested in that function is innerFunction. Math hasn’t always been my strong suit, but 1 + 1 = 2 in my book. Each function object has its own set of variables, which are resolved in each function’s scope.

A Closure Has its Own Scope

Closures can’t be fully understood without a firm grounding in scope. JavaScript’s scope mechanism is what allows each function to have its own topping variable, and without it we might have too much pepperoni, too little ham, or *gasp* … some anchovies at our pizza party. Let’s use a quick illustration to better illustrate this idea.

Functions are executed using the scope that was in effect when the function was defined. It has nothing to do with the scope in effect when the function is called.

Variable Accessibility Works Outside-In

The green arrows show that accessibility works from the outside in. Variables defined in the scope outside of a function are accessibile from within it.

If we were to omit the topping variable from inside the pizzaParty function, then we would get a message like “This pizza is all about the anchovi”, but since pizzaParty has a topping variable within its own scope; those salty suckers will never get near our pizza party.

Likewise, the numSlices parameter can be accessed from within innerFunction because it is defined in the scope above – in this case the scope of pizzaParty.

Variable Accessibility Does Not Work Inside-Out

The red arrows show that variables in scope for a function are never accessible outside of that function. This is the case only when a variable meets one of the following conditions:

  1. The var keyword is being used.
  2. The variable is a parameter to the function or an outer function.
  3. The variable is a nested function.

Omitting the var keyword when setting a variable will cause JavaScript to set the closest named variable in outer functions all the way up to the global scope. So, using our example, the ham topping in innerFunction cannot be accessed from pizzaParty, and the pepperoni topping in pizzaParty cannot be accessed out in the global scope where the anchovi dwells.

JavaScript Uses Lexical Scoping

Lexical scope means functions are executed using the variable scope in effect when the function was defined. It has nothing to do with the scope in effect when the function is called. This fact is crucial to unlocking the power of closures.

Now that we understand what a closure is, and what scope means for closures, let’s dive into some classic use cases.


Using Closures For Privacy

Closures are the way to conceal your code from the public eye. With closures, you can easily have private members that are shielded from the outside world:

(function(exports){

	function myPrivateMultiplyFunction(num,num2) {
		return num * num2;
	}

	//equivalent to window.multiply = function(num1,num2) { ...
	exports.multiply = function(num1,num2) {
		console.log(myPrivateMultiplyFunction(num1,num2));
	}

})(window);

With closures, you can easily have private members that are shielded from the outside world.

Let’s break it down. Our top level function object is an anonymous function:

(function(exports){
	
})(window);

We invoke this anonymous function right away. We pass it the global context (window in this case) so we can “export” one public function, but hide everything else. Because the function myPrivateMultiplyFunction is a nested function, it exists only within the scope of our closure; so we can use it anywhere inside this scope, and only in this scope.

JavaScript will hold a reference to our private function for use inside the multiply function, but myPrivateMultiplyFunction cannot be accessed outside of the closure. Let’s try this out:

multiply(2,6) // => 12
myPrivateMultiplyFunction(2,6) // => ReferenceError: myPrivateMultiplyFunction is not defined

The closure has allowed us to define a function for private use, while still allowing us to control what the rest of the world sees. What else can closures do?


Using Closures For Meta-Programming

Closures are quite handy when it comes to generating code. Tired of remembering all those pesky key codes for keyboard events? A common technique is to use a key map:

var KeyMap = {
	"Enter":13,
	"Shift":16,
	"Tab":9,
	"LeftArrow":37
};

Then, in our keyboard event, we want to check if a certain key was pressed:

var txtInput = document.getElementById('myTextInput');
txtInput.onkeypress = function(e) {
	var code = e.keyCode || e.which //usual fare for getting the pressed key
	if (code === KeyMap.Enter) {
	    console.log(txtInput.value);
	}
}

Capturing A Moment In Time

The above example isn’t the worst, but we can use meta-programming and closures to make an even better solution. Using our existing KeyMap object, we can generate some useful functions:

for (var key in KeyMap) {

	//access object with array accessor to set "dyanamic" function name
	KeyMap["is" + key] = (function(compare) {
		return function(ev) {
			var code = ev.keyCode || ev.which;
			return code === compare;
		}
	})(KeyMap[key]);

}

Closures are so powerful because they can capture the local variable and parameter bindings of the function in which they are defined.

This loop generates an is function for every key in KeyMap, and our txtInput.onkeypress function becomes a bit more readable:

var txtInput = document.getElementById('myTextInput');
txtInput.onkeypress = function(e) {
	if(KeyMap.isEnter(e)) {
		console.log(txtInput.value);
	}
}

The magic starts here:

KeyMap["is" + key] = (function(compare){
	
})(KeyMap[key]); //invoke immediately and pass the current value at KeyMap[key]

As we loop over the keys in KeyMap, we pass the value referenced by that key to the anonymous outer function and invoke it immediately. This binds that value to the compare parameter of this function.

The closure we are interested in is the one we are returning from inside the anonymous function:

return function(ev) {
	var code = ev.keyCode || ev.which;
	return code === compare;
}

Remember, functions are executed with the scope that was in place when they were defined. The compare parameter is bound to the KeyMap value that was in place during a loop iteration, and so our nested closure is able to capture it. We take a snapshot in time of the scope that was in a effect at that moment.

The functions we created allow us to skip setting up the code variable everytime we want to check the key code, and we now have convenient, readable functions to use.


Using Closures To Extend The Language

At this point, it should be relatively easy to see that closures are vital to writing top notch JavaScript. Let’s apply what we know about closures to augmenting one of JavaScript’s native types (gasp!). With our focus on function objects, let’s augment the native Function type:

Function.prototype.cached = function() {
	var self = this, //"this" refers to the original function
		cache = {}; //our local, lexically scoped cache storage
	return function(args) {
		if(args in cache) return cache[args];
		return cache[args] = self(args);
	};
};

This little gem allows any and every function to create a cached version of itself. You can see the function returns a function itself, so this enhancement can be applied and used like so:

Math.sin = Math.sin.cached();
Math.sin(1) // => 0.8414709848078965
Math.sin(1) // => 0.8414709848078965 this time pulled from cache

Notice the closure skills that come into play. We have a local cache variable that is kept private and shielded from the outside world. This will prevent any tampering that might invalidate our cache.

The closure being returned has access to the outer function’s bindings, and that means we are able to return a function with full access to the cache inside, as well as the original function! This small function can do wonders for performance. This particular extension is set up to handle one argument, but I would love to see your stab at a multiple argument cache function.


Closures in the Wild

As an added bonus, let’s take a look at a couple uses of closures in the wild.

jQuery

Sometimes, the famous jQuery $ factory is not available (think WordPress), and we want to use it in the way we typically do. Rather than reach for jQuery.noConflict, we can use a closure to allow functions inside to have access to our $ parameter binding.

(function($){
	$(document).ready(function(){
		//business as usual....
	});
})(jQuery);

Backbone.js

On large Backbone.js projects, it might be favorable to have your application models private, and then expose one public API on your main application view. Using a closure, you can easily acheive this privacy.

(function(exports){

var Product = Backbone.Model.extend({
    urlRoot: '/products',
});

var ProductList = Backbone.Collection.extend({
    url: '/products',
    model: Product
});

var Products = new ProductList;

var ShoppingCartView = Backbone.View.extend({

    addProduct: function (product, opts) {
        return CartItems.create(product, opts);
    },

    removeProduct: function (product, opts) {
        Products.remove(product, opts);
    },

    getProduct: function (productId) {
        return Products.get(productId);
    },

    getProducts: function () {
        return Products.models;
    }
});

//export the main application view only
exports.ShoppingCart = new ShoppingCartView;

})(window);

Conclusion

A quick recap of what we learned:

  • A closure is nothing more than a function object with a scope.
  • Closures get their name by the way they “close” over their contents.
  • Closures cash in big time on JavaScript’s lexical scope.
  • Closures are the way to achieve privacy in JavaScript.
  • Closures are able to capture the local variable and parameter bindings of an outer function.
  • JavaScript can be powerfully extended with some closure magic.
  • Closures can be used with many of your favorite libraries to make them even cooler!

Thanks so much for reading! Feel free to ask any questions. Now let’s enjoy the pizza party!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://github.com/stayclassytally/ Bryan Paronto

    Hey Brian, Great article! For clarification, should line 34 of your backbone example be:

    export.ShoppingCart = new ShoppingCartView;

    • http://www.brianscaturro.com Brian Scaturro

      Thanks for the kind words! Should actually be exports.ShoppingCart = new ShoppingCartView; I’ll get that updated asap.

    • Eugene Fedorov

      All that is within the (function(exports){ … })(window); not available from the global scope.
      But line 34:

      export.ShoppingCart = new ShoppingCartView;

      makes this object(ShoppingCart) available. Like this console.log(ShoppingCart);
      Sorry for my English.

  • Shahriar

    Nice article :-)

  • http://www.redcrown.co Matthew

    In the backbone example, I believe you switched ‘exports’ with ‘export’.
    I like aliasing window with ‘global.’

  • Joy

    Very good article. :-) (Y)

  • Franklin Javier

    Great article.

  • http://developnew.com Developnew

    Nice Article…..short and simple…:)

  • Alchemication

    Thanks! Bit easier to understand than Crockfords nested recursive Fibonacci-es (still loving Doug’s lectures!!)

  • pixelBender67

    Good tutorial , keep them coming JS rocks
    - \m/ | \m/-

  • stefan

    Great article. THX!

  • http://www.nicelittlewebsite.co.uk Dave Mellett

    Nicely written. It’s so difficult to explain advanced Javascript, you’ve done a great job – let’s have more..!

  • kasakka

    Very nice and simple.

  • elkaz

    Just thought I’d mention the section where you create the cache method on the Function object should be a self executing function on definition:

    Function.prototype.cached = (function() {
    var self = this, //”this” refers to the original function
    cache = {}; //our local, lexically scoped cache storage
    return function(args) {
    if(args in cache) return cache[args];
    return cache[args] = self(args);
    };
    })();

    • http://www.brianscaturro.com Brian Scaturro

      We actually want this method to return a “cached” version of the function only when it is invoked (as in the example with Math.sin). No need to invoke on definition.

  • Bassu

    I think I understand now. :-) Thanks for doing the article, enjoyed reading it.

  • Bryce Darling

    elkaz,

    Could you show us an example of how we should use your alternate proposed cached function?

    When I tried out your code like how the article shows I get the following error:

    Math.sin = Math.sin.cached();
    TypeError: object is not a function

    I added some console.log statements and comments to Brian’s code which might help you see how the function is working:

    Function.prototype.cached = function() {
    var self = this, // “this” refers to the original function
    cache = {}; // our local, lexically scoped cache storage
    return function(args) {
    // check if args (the key) is in the cache
    if (args in cache) {
    // found the args key in the cache
    // return the cached value
    console.log(‘cache hit: ‘ + args + ‘ = ‘ + cache[args]);
    return cache[args];
    }
    // failed to find args key in the cache
    // compute it using the original function
    // store the result in the cache and return the result
    console.log(‘cache miss: ‘ + args);
    return cache[args] = self(args);
    };
    };

    Math.sin(1);
    cache miss: 1
    0.8414709848078965
    Math.sin(1);
    cache hit: 1 = 0.8414709848078965
    0.8414709848078965

  • http://danielhgma.wordpress.com/ Daniel

    Cool article. Thanks!

  • Felix

    Very interesting, good example and useful.

  • http://hellowoo.com Łukasz

    Brian we all know you secretly love anchovis……great tutorial brother man.

  • Tadd

    Great article man! Well written and illustrated. I’ll have to walk over and high-five you!

  • Rey

    Why doesn’t your cached function work on the console’s log function?

    • http://www.brianscaturro.com Brian Scaturro

      console.log is not a single argument function. I can’t think of too many real world use cases where you would want to cache this anyways.

    • elkaz

      See my comment above.

      • Rey

        I think I got an error using that too.

  • http://www.invalidusername.com Jeremiah

    Excellent overview and examples. Now I want pizza for dinner.

  • deepak kashyap

    this is a outstanding explanation of Closures

  • http://www.wpsquare.com/ Bharat Chowdary

    I really dont know much about this, but after finishing this article I got some knowledge over that.

  • seltar

    I prefer the closure where you provide the window, document, $ and undefined variable, ensuring no 3rd party code has overridden them.

    (function(window, document, $, undefined){
    /* your code here */
    })(this, this.document, this.jQuery);

    Made an extensive example here;
    http://jsfiddle.net/seltar/HPmFW/2/

  • https://gist.github.com/2575089 danneu

    Awesome article. I’m on a closure exposure binge alternating between random articles and writing my own closures until I get it.

    I just started learning JS/Coffeescript the other week and took a stab at your multi-arg challenge.

    The only idea I had was to join the arg list into a string and use it as the cache key.

    Math.max 1, 2, 3
    cache would look like {“1,2,3″: 3}
    Math.max 3, 4, 5
    cache becomes {“1,2,3″: 3, “3,4,5″: 5}

    As usual, I probably am missing a painfully obvious solution.

    https://gist.github.com/2575089

    # Cache a func with multiple args like Math.max(1, 2, 3)
    Function::cached = ->
    cache = {}
    (args…) => # Note: could’ve used a regular `->` and keep the `self = @`
    argsKey = args.join()
    if argsKey of cache
    console.log “Hitting cache with #{argsKey}”
    return cache[argsKey]
    console.log “Cache miss…”
    return cache[argsKey] = @(args…)

    Math.max = Math.max.cached()
    Math.max 1, 2, 3 # cache miss
    Math.max 3, 4, 5 # cache miss
    Math.max 1, 2, 3 # cache hit
    Math.max 1, 2, 3, 4 # cache miss
    Math.max 1, 2, 3, 4 # cache hit

  • https://twitter.com/#!/rmnbrd Romain Billard

    Great article. I have just a little question : What font is used on screenshots ?
    Thanks.

    • http://www.brianscaturro.com Brian Scaturro

      It is the default font for Sublime Text 2′s Monokai theme. I believe it’s Monaco.

      • https://twitter.com/#!/rmnbrd Romain Billard

        No, I checked and it’s not Monaco. I had never see this font before.
        If someone have the name of this awesome font… Thanks.

    • Watabou

      It’s Menlo, which is available by default on OS X Snow Leopard and Lion. I don’t think it’s available on other systems. A great programming font and my favorite after Monaco.

      • abdo

        i think it’s the consolas font (windows) not the menlo font :)

    • Watabou

      It’s Menlo, which is available by default on OS X Snow Leopard/Lion.

  • http://www.reviewken.com Kiran Chikkala

    good explanation…

  • http://tecnologia.webdesignargentina.com Nacho

    Really nice !! Thanks alot!! Cheers ! I want more about top notch JavaScript.

  • angel

    A dumb question..which is the difference between a closure and a monad??…thanks so much!!!!!

    • http://www.brianscaturro.com Brian Scaturro

      Hmmmm.. well closures are a lot broader than something that just encapsulates computations. Closures can yield all kinds of side effects; they aren’t just a way to group program logic. Closures can wrap around all kinds of disparate functionality as well as data. For example, the whole of the jQuery libary is wrapped in a closure.

  • Bobby Digital

    Can someone please explain why you can only access the myPrivateMultiplyFunction within exports.multiply function and not outside of it. I understand closure. I just dont understand exactly whats happening here.

    (function(exports){

    myPrivateMultiplyFunction = function(num,num2) {
    return num * num2;
    }

    exports.multiply = function(num1,num2) {
    console.log(myPrivateMultiplyFunction(num1,num2));
    }

    multiply(2,6) // => 12
    myPrivateMultiplyFunction(2,6) // => ReferenceError: myPrivateMultiplyFunction is not defined

    })(window);

    • http://www.brianscaturro.com Brian Scaturro

      Well your example there creates a global function. When you do myPrivateMultiplyFunction = … without the var keyword it will work outside of the closure. If you use the var keyword or the function keyword, it is scoped to the function that contains it ( in this case the (function(exports){}) function).

      The example from the article uses the function keyword so the inner myPrivateMultiplyFunction is scoped to the outer closure, and therefore cannot be accessed from outside of it.

  • http://www.droidedition.com/ Raj

    Really nice.. and very brilliant explanation.. Good work..!!

  • Runar

    I’m confused.
    Isn’t this article stating the opposite of this one? http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/
    Cause here we are nesting functions to obtain privacy. But I’m a beginner, so I might be wrong.

    • http://www.wdonline.com/ Jeremy McPeak

      No. As I mentioned in the linked article, not every nested function is bad. In fact, I’ll quote what I said and emphasis the key difference:

      It’s important to note that this anti-pattern does not apply to all instances of nested functions, but it is typically defined by two characteristics. First, the creation of the function in question is usually deferred—meaning that the nested function is not created by the JavaScript engine at load-time. That in and of itself isn’t a bad thing, but it’s the second characteristic that hinders performance: the nested function is repeatedly created due to repeated calls to the outer function. So while it may be easy to say “all nested functions are bad,” that is certainly not the case, and you will be able to identify problematic nested functions and fix them to speed up your application.

      • Runar

        Thaks for the reply.
        Let me see if I got this. Are you saying that one should avoid nesting when the function is generic and thus it should rather be added to the prototype cause every instance will be able to use the prototype function without modification. But if a function is uniqe it should be nested?

  • http://www.etpio.com Tegan Snyder

    Excellent write up!

  • http://www.besigner.com.mx Jesús García

    Hi Brian. Great article. For the first time I understand all about closures, and all thanks to you. I really appreciate your time and effort to write articles like this.

    • http://www.brianscaturro.com Brian Scaturro

      Glad you liked it!

  • emrah

    Good subject, Bad example. i had to always go back and look where pepporoni is or where anchovi is. can you keep it simple and focus the subject.