Overview

Before ES6, RequireJS or seaJS was used to implement modularization (these are modularization libraries based on the AMD specification and the CMD specification, respectively).

ES6 introduced modularization, with the design philosophy of determining module dependencies and input/output variables at compile time.

ES6 modularization is divided into two modules: export (@) and import.

Features

ES6 modules automatically enable strict mode, whether or not you add it at the top of the module.use strict;。

Modules can import and export various types of variables, such as functions, objects, strings, numbers, booleans, classes, etc.

Each module has its own context. Variables declared in each module are local variables and do not pollute the global scope.

Each module is loaded only once (it is a singleton). If the same file in the same directory is loaded again, it is read directly from memory.

export and import

Basic Usage

Modules import and export various types of variables, such as strings, numbers, functions, and classes.

  • Exported function declarations and class declarations must have names (the export default command is a separate consideration).
  • Not only can declarations be exported, but references (such as functions) can also be exported.
  • The export command can appear anywhere in the module, but it must be at the top level of the module.
  • The import command is hoisted to the top of the entire module and executed first.
/*-----export [test.js]-----*/ let myName = "Tom"; let myAge = 20; let myfn = function(){ return "My name is" + myName + "! I'm '" + myAge + "years old." } let myClass = class myClass { static a = "yeah!"; } export { myName, myAge, myfn, myClass } /*-----import [xxx.js]-----*/ import { myName, myAge, myfn, myClass } from "./test.js"; console.log(myfn());// My name is Tom! I'm 20 years old. console.log(myAge);// 20 console.log(myName);// Tom console.log(myClass.a );// yeah!

It is recommended to use curly braces to specify a set of variables to be exported, written at the end of the document, to clearly define the exported interfaces.

Functions and classes both need corresponding names. Exporting at the end of the document also avoids the lack of corresponding names.

Usage of as

The interface names exported by the export command must have a one-to-one correspondence with the variables inside the module.

The imported variable names must match the exported interface names; the order can be different.

/*-----export [test.js]-----*/ let myName = "Tom"; export { myName as exportName } /*-----import [xxx.js]-----*/ import { exportName } from "./test.js"; console.log(exportName);// TomUsageasRename the exported interface names to hide the variables inside the module./*-----export [test1.js]-----*/ let myName = "Tom"; export { myName } /*-----export [test2.js]-----*/ let myName = "Jerry"; export { myName } /*-----import [xxx.js]-----*/ import { myName as name1 } from "./test1.js"; import { myName as name2 } from "./test2.js"; console.log(name1);// Tom console.log(name2);// Jerry

When interface names exported by different modules have duplicate naming, use as to redefine the variable names.

Features of the import command

Read-only property: In the script that loads the module, it is not allowed to rewrite the reference of the interface. That is, you can modify the property values of imported variables that are of object type, but you cannot modify the values of imported variables that are of primitive type.

import {a} from "./xxx.js" a = {}; // error import {a} from "./xxx.js" a.foo = "hello"; // a = { foo : 'hello' }

Singleton pattern: Executing the same import statement multiple times will only execute once, not multiple times. Importing the same module and declaring different interface references will declare the corresponding variables, but the import will only execute once.

import { a } "./xxx.js"; import { a } "./xxx.js"; //Equivalent to import { a } "./xxx.js"; import { a } from "./xxx.js"; import { b } from "./xxx.js"; //Equivalent to import { a, b } from "./xxx.js";

Static execution feature: import is statically executed, so expressions and variables cannot be used.

import { "f" + "oo" } from "methods"; // error let module = "methods"; import { foo } from module; // error if (true) { import { foo } from "method1"; } else { import { foo } from "method2"; } // error

The export default command

  • In a file or module, there can be multiple export and import statements, but only one export default.
  • In export default, default is the corresponding exported interface variable.
  • When exporting using export, you must add { } when importing; export default does not require it.
  • The members exposed by export default can be received using any variable.
var a = "My name is Tom!"; export default a; //Only one export default var c = "error"; //error, default is already the corresponding exported variable, and cannot be followed by a variable declaration statement. import b from "./xxx.js"; //No {} needed; use any variable to receive it.

Combined Usage

Note: import() is a proposal; we will not elaborate on it here for now.

export and import can be used in the same module, with the following features:

  • You can rename the exported interfaces, including default.
  • Combining export and import can also export everything; the interfaces exported by the current module will override the inherited exports.
export { foo, bar } from "methods"; //It is roughly equivalent to the following two statements, except that the above import/export method does not import foo and bar into this module. import { foo, bar } from "methods"; export { foo, bar }; /*------- Feature 1 --------*/ //Ordinary renaming export { foo as bar } from "methods"; //Re-export foo as default export { foo as default } from "methods"; //Re-export default as foo export { default as foo } from "methods"; /*------- Feature 2 --------*/ export * from "methods";