How Closures Work in JavaScript: An Overview

Closures are a very powerful yet underused feature unique to of JavaScript (and other ECMAScript languages). They essentially provide your code with private variables that other scripts can't access. This is accomplished by exploiting three interesting features (or "quirks") of JavaScript:

  1. JavaScript is executed in-place
  2. Functions can be self-executed
  3. Variables inside a function exist after a function completes

Let's start by examining some JavaScript that doesn't use closures. Let's say your webpage has a button that counts how many times it was clicked:

	var incrementCount = function() {
		myButton.value = ++count;
	}

	var myButton = document.getElementById('clickme');
	var count = 0;

	myButton.onclick = incrementCount;

This code is fairly straight-forward and works just fine. However, all the function and variables exist with the scope of that page, which makes them vulnerable to colliding with other scripts. Imagine our site also contained a function that counted the number of characters in a text box:

	function countLetters(someTextbox) {
		count = someTextbox.length;
		alert('There are ' + count + ' letters');
	}

Both functions are using the same global "count" variable, even if they were loaded in separate scripts. You might avoid this in practice, but there's no guarantee that other scripts will.

Clousures solve this problem by exploiting those previously mentioned features. We can rewrite the incrementCount() function like this:

	var myButton = document.getElementById('clickme');
	
	var incrementCount = function() {
		var count = 0;

		return function(){
			myButton.value = ++count;
		}
	}();
	
	myButton.onclick = incrementCount;

The key here is that incrementCount is a self-executing function, which take the form:

	var myFunction = function() { ... } ();

Note the extra set of parens at the end. This tells JavaScript to execute the function immediately after its been parsed, instead of waiting for some other code to call that function. Because the function is immediate executed, it can return something back into the myFunction variable. If you look at the revised incrementCount() code, you see that we returned an inner function.

Because JavaScript runs code in-place, calls to incrementCount() run the inner function in the same location it was defined. Because variables can exist after a function has execute, the value of "count" is maintained. And due to scope rules, only the inner function may access that "count" variable. This behavior is somewhat similar to private variables in object-oriented programming - the inner functions may reference this and change the values, but everything else is unaware of its existance and unable to read/modify it.

jQuery, one of the most popular JS libraries, uses closures to maintain the integrity of its functions and variables. It also uses a self-executing function to further protect it's scope. Here are the first and last lines of the core library:

	(function( window, undefined ) {
		// Define a local copy of jQuery
		var jQuery = ...
		
		// Expose jQuery to the global object
		window.jQuery = window.$ = jQuery;
	})(window);

All the core jQuery methods and properties are defined within that closure self-executing function. This prevents it from interfering with other scripts and vice versa. At the very end, they "expose jQuery to the global object" so that other code can easily reference and use it.

But the usefulness of closures in this case doesn't stop there. Did you notice the self-executing function expects two parameters but only receives one?

	(function( window, undefined ) { ... })(window);

The "window" object is passed in so that jQuery can expose itself when ready. But nothing is ever assigned to the "undefined" variable. This neat trick ensures that "undefined" is actually set to an undefined value, such that:

	typeof undefined == "undefined"

You can try setting "var undefined = 12345;" elsewhere on your site and jQuery will be unaffected by it. This brilliant line saves developers from writing extra code:

	// How you would check a variable has been defined (or argument has been passed) without the closure trick:
	if (typeof someVar == "undefined") ...
	// Versus this:
	if(someVar === undefined)

Closures aren't the easiest concept to wrap your head around, but once understood they can be a powerful tool, especially when combined with self-executing functions. Once you master closures, you can move on to more-advanced JavaScript concepts like design patterns, which I'll be covering in futute blog posts.

Corrections: This article initially stated that closures were "unique" to JavaScript, instead of being a design feature relatively uncommon among some other languages. Additionally, I mistakenly referred to jQuery's self-executing function as a "closure", instead of clarifying that the SEF contained a closure.

About the Author

GoogleColin O'Dell first started programming on an old Apple II-e at the age of 8. Within four years, he mastered several BASIC variants and sold his...

 
 

On-Demand Webinar

Check out this new webinar about how to optimize your site speed with new open source technologies.

Categories

View All

Testimonials

“Unleashed Technologies is a pleasure to work with. We needed an unusual, non-cookie-cutter web site on a very tight...

Read More
Paul Jakubik
PureDiscovery Corporation

Mike and his team have taken over a web site that was limping along, with an extensive list of problems and a weak design...

Read More
Laura Perry, Marketing Director
Whiteford | Taylor | Preston

“It was a pleasure working with Michael Spinosa and his team from Unleashed Technologies.

Jordan Sopher
Eyemaginations, Inc.