Wednesday, February 27, 2013

Playing with ECMAScript.Harmony Modules using Traceur

As aI was a preparing a presentation on AMD and RequireJS I started looking ahead at the modules proposed for ECMAScript.Harmony.  In Addy Osmani's article Writing Modular JavaScript With AMD, CommonJS & ES Harmony he mentioned called Traceur which is a JavaScript compiler for ECMAScript Harmony syntax. This allows developers to give the future of JavaScript a test drive today.

One of the new features coming in Harmony that has me excited is modules. Modules will be a way to encapsulate code and explicitly define its dependencies and public API. ES Harmony gives us three new keywords for modules: module, import, and export. The module keyword is used to initialize a new module, the import keyword declares dependencies to import from a module into a context, and the export keyword explicitly declares public properties that will be available for other modules to import.

In addition Harmony modules:
  • are statically scoped
  • have the this keyword bound to the global object


Before we are able to write modules today we'll need an environment that supports Harmony syntax. For this we'll use Google's Traceur compiler. In order to implement Traceur you'll need three things:
  1. Traceur library file
  2. Traceur bootstrap file
  3. Harmony code
Adding the Traceur library and bootstrap to an application is as easy as adding the scripts to a web page:

Now that we have a compiler in place we just need some code for it to compile. To do this simply create a script block with a type of script/traceur.

When the page loads Traceur will compile your Harmony code to JavaScript that works in today's modern browsers.

For your convince I've created a JS Bin with Traceur ready to go on JS Bin. In addition there is an online compiler you can use here:

Now that we have an environment that supports Harmony to work in lets take a look at modules.

Playing With Modules

First I'd like to point modules aren't meant to be classes, there the class keyword for that. According to the ECMAScript Wiki modules are a
"Standardized mechanism for creating libraries"
Modules do not create a new execution context, the this keyword in a module is bound to the global object. Looking at the code that Traceur outputs for a simple module definition shows this:

Even though a module does not get a new execution context , it does get a new static scope. In the following code I am creating a new module called carFactory that exports a variable named ford into the global namespace. Calling ford.wheels results in '4' and trying to access carFactory's internal wheels variable results in an error:

JS Bin

Its also important to note that doing an import * will import the variables from the modules with the same names the have in the module.

A module can also have multiple exports as shown in the following code (note the syntax for importing multiple exports in a single statement):

JS Bin

A module also doesn't only have to export objects, it can export anything:

JS Bin

Variables that are imported can also renamed the from modules using the following syntax:

JS Bin

Lastly modules can be nexted. Nested modules have privileged access to their parent modules scope. Nested modules are also private to their parent modules scope unless they are explicitly exported. Here is an example of a public nested module that accesses its parents scope:

JS Bin


Modules in Harmony look like they are going to be very useful and there's a lot you can do with them.  They help reduce the need for the overuse of the function keyword and reduce the need for patterns like AMD and complex loaders RequireJS and CurlJS (of which I am currently a huge fan).   For more reading on modules I suggest checking out the modules section on the ECMAScript Harmony WIKI.