HTML5 Zone is brought to you in partnership with:

Hi, I’m David Padbury. I work at Lab49 in New York creating advanced applications for the finance industry. I spend most of my time developing complex HTML5 and JavaScript front-end systems but also often deal with Java, .NET and other Enterprise type stuff. I do a lot of talking on HTML5, JavaScript and occasionally node.js at user groups and conferences. I’m currently focused on helping developers familiar with more traditional thick client technologies such as WPF, Silverlight, Flex or Swing understand how similar applications will be built in HTML5. None of the views I publish here represent the views of my employer. David has posted 1 posts at DZone. View Full User Profile

JavaScript Modules

01.24.2012
| 8695 views |
  • submit to reddit

One of the first challenges developers new to JavaScript who are building large applications will have to face is how to go about organizing their code. Most start by embedding hundreds of lines of code between a <script> tag which works but quickly turns into a mess. The difficultly is that JavaScript doesn’t offer any obvious help with organizing our code. Literally where C# has using, Java has import - JavaScript has nothing. This has forced JavaScript authors to experiment with different conventions and to use the language we do have to create practical ways of organizing large JavaScript applications.

The patterns and tools and practices that will form the foundation of Modern JavaScript are going to have to come from outside implementations of the language itself

- Rebecca Murphy

 

The Module Pattern

One of the most widely used approaches to solve this problem is known as the Module Pattern. I’ve attempted to explain a basic example below and talk about some of it’s properties. For a much better description and a fantastic run down of different approaches take a look at Ben Cherry’s post – JavaScript Module Pattern: In-Depth.

(function(lab49) {

	function privateAdder(n1, n2) {
		return n1 + n2;
	}

	lab49.add = function(n1, n2) {
		return privateAdder(n1);
	};

})(window.lab49 = window.lab49 || {});

 

In the above example we’ve used a number of basic features from the language to create constructs like what we see in languages like C# and Java.

Isolation


You’ll notice that the code is wrapped inside a function which is invoked immediately (check the last line). By default in the browser JavaScript files are evaluated in the global scope so anything we declared inside our file would be available everywhere. Imagine if in lib1.js we had a var name = '...' statement then in lib2.js we had another var name = '...' statement. The second var statement would replace the value of the first – not good. However as JavaScript has function scoping, in the above example everything is declared in it’s own scope away from the global. This means anything in this function will be isolated from whatever else is going on in the system.

Namespacing


In the last line you’ll notice that we’re assigning window.lab49 to either itself or to an empty object literal. It looks a bit odd but let’s walk through an imaginary system where we have a number of js files all using the above function wrapper.

The first file to get included will evaluate that OR statement and find that the left hand side is undefined. This is a falsely value so the OR statement will go ahead and evaluate the right hand side, in this case an empty object literal. The OR statement is actually an expression that will return it’s result and go ahead and assign it to the global window.lab49.

Now the next file to use this pattern will get to the OR statement and find that window.lab49 is now an instance of an object – a truthy value. The OR statement will short circuit and return this value that is immediately assigned to itself – effectively doing nothing.

The result of this is that the first file in will create our lab49 namespace (just a JavaScript object) and every subsequent file using this construct will just reuse the existing instance.

Private State


As we just talked about due to being inside a function, everything declared inside it is in the scope of that function and not the global scope. This is great to isolate our code but it also has the effect that no one could call it. Pretty useless.

As we also just talked about we’re creating a window.lab49 object to effectively namespace our content. This lab49 variable is available globally as it’s attached to the window object. To expose things outside of our module, publically you may say, all we need to do attach values to that global variable. Much like we’re doing with our add function in the above example. Now outside of our module our add function can be called with lab49.add(2, 2).

As another result of declaring our values inside of this function, if a value isn’t explicitly exposed by attaching it to our global namespace or something outside of the module there is no way for external code to reach it. In practice, we’ve just created some private values.

CommonJS Modules


CommonJS is a group primarily made up of authors of server-side JavaScript runtimes who have attempted to standardize exposing and accessing modules. It’s worth noting however that their proposed module system is not a standard from the same group that creates the JavaScript standard so it’s become more of an informal convention between the authors of server-side JavaScript runtimes.

I generally support the CommonJS idea, but let’s be clear: it’s hardly a specification handed down by the gods (like ES5); it’s just some people discussing ideas on a mailing list. Most of these ideas are without actual implementations.

- Ryan Dahl, creator of node.js


The core of the Modules specification is relatively straight forward. Modules are evaluated in their own context and have a global exports variable made available to them. This exports variable is just a plain old JavaScript object which you can attach things too, similar to the namespace object we demonstrated above. To access a module you call a global require function and give an identifier for the package you are requesting. This then evaluates the module and returns whatever was attached to the exports. This module will then be cached for subsequent require calls.

// calculator.js
exports.add = function(n1, n2) {

};

// app.js
var calculator = require('./calculator');

calculator.add(2, 2);


If you’ve ever played with Node.js you’ll probably find the above familiar. The way that Node implements CommonJS modules is surprisingly easy, looking at a module inside node-inspector (a Node debugger) will show its content wrapped inside a function that is being passed values for exports and require. Very similar to the hand rolled modules we showed above.


There’s a couple of node projects (Stitch and Browserify) which bring CommonJS Modules to the browser. A server-side component will bundle these individual module js files into a single js file with a generated module wrapper around them.

CommonJS was mainly designed for server-side JavaScript runtimes and due to that there’s a couple of properties which can make them difficult for organization of client-side code in the browser.

  • require must return immediately – this works great when you already have all the content but makes it difficult to use a script loader to download the script asynchronously.
  • One module per file – to combine CommonJS modules they need to be wrapped in a function and then organized in some fashion. This makes them difficult to use without some server component like the ones mentioned above and in many environments (ASP.NET, Java) these don’t yet exist.

Asynchronous Module Definition


The Asynchronous Module Definition (commonly known as AMD) has been designed as a module format suitable for the browser. It started life as a proposal from the CommonJS group but has since moved onto GitHub and is now accompanied by a suite of tests to verify compliance to the AMD API for module system authors.

The core of AMD is the define function. The most common way to call define accepts three parameters – the name of the module (meaning that it’s no longer tied to the name of the file), an array of module identifiers that this module depends on, and a factory function which will return the definition of the module. (There are other ways to call define – check out the AMD wiki for full details).

define('calculator', ['adder'], function(adder) {
	return {
		add: function(n1, n2) {
			return adder.add(n1, n2);
		}
	};
});


Because of this module definition is wrapped in the define call it means you can happily have multiple modules inside a single js file. Also as the module loader has control over when the define module factory function is invoked it can resolve the dependencies in its own time – handy if those modules have to first be downloaded asynchronously.

A significant effort has been made to remain compatible with the original CommonJS module proposal. There is special behavior for using require and exports within a module factory function meaning that traditional CommonJS modules can be dropped right in.

AMD looks to be becoming a very popular way to organize client-side JavaScript applications. Whether it be through module resource loaders like RequireJS or curl.js, or JavaScript applications that have recently embraced AMD like Dojo.

Does this mean JavaScript sucks?


The lack of any language level constructs for organization of code into modules can be quite jarring for developers coming from other languages. However as this deficiency forced JavaScript developers to come up with their own patterns for how modules were structured we’ve been able to iterate and improve as JavaScript applications have evolved. Follow the Tagneto blog for some insight into this.

Imagine if this type of functionality had been included in the language 10 years ago. It’s unlikely they would have imagined the requirements for running large JavaScript applications on the server, loading resources asynchronously in the browser, or including resources like text templates that loaders like RequireJS are able to do.

Modules are being considered as a language level feature for Harmony/ECMAScript 6. Thanks to the thought and hard work of authors of module systems over the past few years, it’s much more likely that what we end up getting will be suitable for how modern JavaScript applications are built.


Source: http://blog.davidpadbury.com/2011/08/21/javascript-modules/

Published at DZone with permission of its author, David Padbury.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Ibrahim Levent replied on Wed, 2012/01/25 - 3:19pm

We're about to refactor our js library with Module pattern. I've searched the net for a clean and usable AMD pattern implementation and found following hardly. It was the best article for me, for readers' information, I share it: http://libraryinstitute.wordpress.com/2010/12/01/loading-javascript-modules/

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.