DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Coding
  3. JavaScript
  4. JavaScript Modules

JavaScript Modules

David Padbury user avatar by
David Padbury
·
Jan. 24, 12 · Interview
Like (0)
Save
Tweet
Share
9.87K Views

Join the DZone community and get the full member experience.

Join For Free

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/

JavaScript

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • gRPC on the Client Side
  • Container Security: Don't Let Your Guard Down
  • Unlocking the Power of Elasticsearch: A Comprehensive Guide to Complex Search Use Cases
  • Real-Time Analytics for IoT

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: