Learning JavaScript Data Structures and Algorithms
上QQ阅读APP看书,第一时间看更新

Modules

Node.js developers are already familiar with working with modules by using the require statement (CommonJS modules). There is also another popular JavaScript standard for modules which is the Asynchronous Module Definition (AMD). RequireJS is the most popular AMD implementation. ES2015 introduced an official module feature in the JavaScript specification. Let's create and use some modules.

The first module we will create contains two functions to calculate the area of geometric figures. In a file (17-CalcArea.js), add the following code:

const circleArea = r => 3.14 * (r ** 2); 
 
const squareArea = s => s * s; 
 
export { circleArea, squareArea }; // {1} 

This means we are exposing both functions so other files can use them ({1}). Only exported members are visible by other modules or files.

In our main file for this example (17-ES2015-ES6-Modules.js), we will use the functions declared in the 17-CalcArea.js file. The following snippet is the code that consumes the two functions:

import { circleArea, squareArea } from './17-CalcArea'; // {2} 
 
console.log(circleArea(2)); 
console.log(squareArea(2)); 

First, we need to import the functions we want to use in this file ({2}), and after importing them, we can evoke them.

If we wanted to use the circleArea function, we could import only this function as well:

import { circleArea } from './17-CalcArea'; 

Basically, modules are JavaScript code declared in separate files. We can import the functions, variables, and classes from other files directly in the JavaScript code (without the need to import several files in the HTML first—and in the correct order—as we used to do a few years ago before JavaScript was modern and popular). Modules allow us to better organize our code in case we are creating a library or working on a big project.

There is also the option to use the exported member with a different name when we do the import, as follows:

import { circleArea as circle } from './17-CalcArea'; 

Or, we can rename the name of the exported functions while exporting them:

export { circleArea as circle, squareArea as square }; 

In this case, the exported members need to be imported with the exposed name, not the name used internally, as follows:

import { circle, square } from './17-CalcArea'; 

There are also a few different ways we can import the functions in a different module:

import * as area from './17-CalcArea'; 
 
console.log(area.circle(2)); 
console.log(area.square(2)); 

In this case, we can import the entire module as a single variable and evoke the exported members as if they were attributes or methods of a class.

It is also possible to add the export keyword in front of each function or variable we want to expose. We do not need to have an export declaration at the end of the file:

export const circleArea = r => 3.14 * (r ** 2); 
export const squareArea = s => s * s; 

Suppose we only have a single member in the module and we want to export it. We can use the export default keyword as follows:

export default class Book { 
  constructor(title) { 
    this.title = title; 
  } 
  printTitle() { 
    console.log(this.title); 
  } 
} 

To import the preceding class in a different module, we can use the following code:

import Book from './17-Book'; 
 
const myBook = new Book('some title'); 
myBook.printTitle(); 

Note that in this case, we do not need to use the curly brackets ({}) around the name of the class. We only use curly brackets in case the module has more than one member exported.

We will use modules when we create our data structures and algorithms library later on in this book.

For more information about ES2015 modules, please read at  http://exploringjs.com/es6/ch_modules.html. You can also check out the complete source code for this example by downloading the source code bundle of this book.