Always Use Closures in Your JavaScript App

Bartosz Olchówka in Programming, on October 20, 2014, Comments

Are JavaScript closures important? Perform the following test in your JavaScript app. Open developer tools in your browser and paste the following in the Console:

_ = jQuery = $ = undefined;

Does your app still work correctly after firing this code? If the answer is no, read on.

Watch out for global objects

Most JavaScript libraries create an object in the global scope. For underscore.js it’s _, and for jQuery it’s $ and jQuery.

When you start using the library, your app becomes dependent on these global objects. If any other library—even by accident—overrides the object, your app will immediately stop working.

A few days ago, our LiveChat app suddenly started to throw JavaScript errors. After 20 minutes, it was working fine back again. The unexpected behavior was a mystery for us since we haven’t updated the app in the meantime.

It turned out that the problem was caused by one of the external libraries that we’re using in our project. The library had a bug which overrode the global _ object that our app was dependent on. The developers had spotted the problem and after 20mins the bug was reverted.

Solution: storing local references to objects

There’s a simple solution that prevents from the similar bugs caused by external libraries. The idea is simple: you must store your own references to the global objects (such as _ or $). Even if the external library overrides them, it will have no impact on your application.

All you need to do is to wrap your whole application code with the following function. It’s called a closure.

(function($, jQuery, _)
{
	// your app code here
}
)($, jQuery, _);

The code creates local references to the objects that are passed as arguments to the function. If any of the global objects are overridden in the future, your app can still call the refer to the local references.


As we’re using Grunt for automated deployment of our app, we’ve prepared a simple task that automatically adds the closure around the app:

grunt.registerTask('app-closure', 'Add closure around the app', function()
{
	var src, closure_start, closure_end;

	// read the original app source
	src = grunt.file.read('app.js');

	// read the closure function that is stored in two files
	closure_start = grunt.file.read('source/closure_start.js');
	closure_end = grunt.file.read('source/closure_end.js');

	// wrap the original app source with the closure
	src = closure_start + src + closure_end;
	grunt.file.write('app.js', src);
});

And here are the closure_start.js and closure_end.js files:

// source/closure_start.js
(function($, jQuery, _)
{
// source/closure_end.js
})($, jQuery, _);

You can read more about JavaScript closures here: Closures — Mozilla Developer Network.