January 18, 2016

ECMAScript 6 'import' - tips to import modules, a new and well received feature in Javascript

Some notes on Modules:

  • Each file / module is executed once it is loaded
  • The declarations remain local to the scope of the module they are in
  • If a module is imported multiple times only one instance of it exists
  • There is only ever one module per file and one file per module

A module can import functions, objects or primitives from other modules. It refers to those modules via 'module specifiers'. These are strings that are relative paths from the importing file, absolute paths or names of module files.


How do i export a function (or an object, a class, etc)?

Let's assume I have a file (module) called delay.js and it contains a couple of functions to set a Timer and add to multiple two numbers together:

/* delay.js */

function multiplyMe(x, y) {
    return x + y;
}
function delay (milliseconds, fn) {
 setTimeout(fn, milliseconds);
}
export { multiplyMe, delay }

The 'export' keyword exports the two functions to use in another module if required.

If you only want to export one function from a file then you can use 'export default':

/* delay.js */

function multiplyMe(x, y) {
    return x + y;
}
function delay (numTime, fn) {
 setTimeout(fn, numTime);
}
export default delay;

I could also export the function itself:

/* delay.js */

export default function(numTime, fn) {
  setTimeout(fn, numTime);
}

You can name the import whatever you like because default exports are not named. i.e. in the 'import' example below we can import this export default by naming it 'delay' even though its not explicitly set as 'delay:


How do i import this function (or an object, a class, etc)?

Let's suppose I have a file called loading.js which I want to access the delay function in delay.js; I write this line to import the exported default from the name of the module it is exported from.

/* loading.js */

import delay from 'delay';

function setTheTimer(num) {
    delay(num, fn);
}

The module loading.js has access to delay() exported as a default from delay.js and uses it to call a timer.

Another example: if i had a file called accessibility.js and I want to export an object I enclose the export default within brackets:

/* accessibility.js */ 

function alert(message) {
  var aDiv = document.createElement('div');
  aDiv.innerHTML = message;
  document.body.appendChild(aDiv);
}

function constructAnotherDiv() {
  let anotherDiv = document.createElement('div');
  document.body.appendChild(anotherDiv);
}

export default {
  alert
}

Within the loading.js module you can reference this exported default property of an object from accessibility.js by calling it within brackets. 

/* loading.js */

import delay from 'delay';
import Accessibility from 'accessibility';

function setTheTimer(num) {
    delay(num, fn);
}

function addAlert(){
    Accessibility.alert('Loading finished, please resume');
}

You reference the exported default object from any member name you would like to call it. Naming it something that reads well as to what it is about is useful.

Other possibilities:

  • Its possible to rename exported functions:
export {multiplyMe as someMaths, delay as aTimer}
  • You can import the entire module someModule into the current scope, containing all the exported bindings from "some-module.js".
import * as someModule from "some-module";
  • Import a member with a more convenient alias if the name is far too long to type out to save time. This inserts aShorterName into the current scope. You can import multiple members by using a comma to separate.
import {reallyReallyLongModuleMemberName as aShorterName} from "my-module";
  • You can import a named variable, class etc from another file by placing the variable name within curly brackets:
import { aVariable } from 'myModule';


Further references:

MDN 'import'


Compatibility:

ECMA6 isn't widely supported yet in all browsers and 'import' isn't as of this date compatible at all, so if this is a requirement you should polyfill back to ECMA5 i.e. using a transpiler such as Babel.