1, Introduction
Module is a collection of program statements that can be named separately and complete certain functions independently (i.e. the collection of program code and data structure).
Two basic features: external features and internal features
-
External features refer to the interface between the module and the external environment (i.e. the way other modules or programs call the module, including input and output parameters and referenced global variables) and the functions of the module
-
Internal characteristics refer to the characteristics of the internal environment of the module (i.e. local data and program code of the module)
Why modularity
-
Code abstraction
-
Code encapsulation
-
code reuse
-
Dependency management
What would our code do without modularity?
-
Variables and methods are not easy to maintain and pollute the global scope
-
Resources are loaded from top to bottom through script tags.
-
Depending on the subjective logic of the environment, more code will be more complex.
-
Large project resources are difficult to maintain, especially in the case of multi person cooperation, the introduction of resources will make people run away
Therefore, there is a need for a mechanism to modularize JavaScript programs, such as
-
CommonJs (typical representative: early node.js)
-
AMD (typical representative: require.js)
-
CMD (typical representative: sea.js)
AMD
Asynchronous module definition (AMD), an asynchronous module definition, loads modules asynchronously. All module dependent statements are defined in a callback function. The callback function will not run until the module is loaded
The representative library is require.js
/** main.js Portal file / main module **/ // First, use config() to specify the path and reference name of each module require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", //The actual path is js/lib/jquery.min.js "underscore": "underscore.min", } }); // Perform basic operations require(["jquery","underscore"],function($,_){ // some code here });
CommonJs
CommonJS It's a set Javascript Module specification for server
// a.js module.exports={ foo , bar} // b.js const { foo,bar } = require('./a.js')
It has the following characteristics:
-
All code runs in the module scope and does not pollute the global scope
-
Modules are loaded synchronously, that is, the following operations can be performed only after loading is completed
-
After the module is executed for the first time, it will be cached. Reloading only returns the cached results. If you want to execute again, you can clear the cache
-
The value returned by require is a copy of the output value, and changes within the module will not affect this value
Since AMD and CommonJs mechanisms exist, what is the difference between ES6 modules?
At the level of language standard, ES6 implements Module, that is, Module function, which can be completely replaced CommonJS and AMD specification has become a common Module solution for browsers and servers
CommonJS And AMD Modules can only determine these things at run time. For example, the commonjs module is an object, and the object properties must be found when inputting
// CommonJS module let { stat, exists, readfile } = require('fs'); // Equivalent to let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
The design idea of ES6 is to be static as much as possible, so that the dependencies of modules and input and output variables can be determined at compile time
// ES6 module import { stat, exists, readFile } from 'fs';
In the above code, only three methods are loaded, and other methods are not loaded, that is ES6 Module loading can be completed at compile time
Static analysis is possible due to compilation and loading. Including the popular typeScript, it also relies on static analysis to realize its functions
2, Use
The strict mode is automatically adopted in the ES6 module. The restriction of the strict mode is not expanded here. After all, this has been specified before ES5
The module function is mainly composed of two commands:
-
export: used to specify the external interface of the module
-
import: used to input functions provided by other modules
export
A module is an independent file. All variables in the file cannot be obtained externally. If you want the external to be able to read a variable inside the module, you must use the export keyword to output the variable
// profile.js export var firstName = 'Michael'; export var lastName = 'Jackson'; export var year = 1958; or // It is recommended to use the following writing method, so that you can instantly determine which variables are output var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export { firstName, lastName, year };
Output function or class
export function multiply(x, y) { return x * y; };
The output variable can be renamed through as
function v1() { ... } function v2() { ... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion };
import
After using the export command to define the external interface of the module, other JS files can load the module through the import command
// main.js import { firstName, lastName, year } from './profile.js'; function setName(element) { element.textContent = firstName + ' ' + lastName; }
Similarly, if you want to alias the input variable, use the as keyword
import { lastName as surname } from './profile.js';
When loading the whole module, you need to use an asterisk*
// circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; } // main.js import * as circle from './circle'; console.log(circle) // {area:area,circumference:circumference}
The input variables are read-only and cannot be modified, but if they are objects, the properties can be modified
import {a} from './xxx.js' a.foo = 'hello'; // Legal operation a = {}; // Syntax Error : 'a' is read-only;
However, even if it can be modified, we do not recommend it. Because after the modification, it is difficult for us to make mistakes
import is often followed by the from keyword, which specifies the location of the module file. It can be a relative path or an absolute path
import { a } from './a';
If there is only one module name, a configuration file is required to tell the engine the location of the module
import { myMethod } from 'util';
In the compilation phase, import will be promoted to the head of the whole module and executed first
foo(); import { foo } from 'my_module';
Repeat the same import several times, and it will only be executed once
import 'lodash'; import 'lodash';
As you can see from the above, when importing the module, you need to know the loaded variable name and function, otherwise it cannot be loaded
If you do not need to know the variable name or function to complete the loading, you need to use the export default command to specify the default output for the module
// export-default.js export default function () { console.log('foo'); }
When loading the module, the import command can specify any name for the function
// import-default.js import customName from './export-default'; customName(); // 'foo'
Dynamic loading
Allows you to dynamically load modules only when needed, without having to preload all modules, which has a significant performance advantage
This new feature allows you to call import() as a function call, passing it as an argument to the path of the module. It returns a promise, which is implemented with a module object, so that you can access the export of the object
import('/modules/myModule.mjs') .then((module) => { // Do something with the module. });
Compound writing
If the same module is input before output in a module, the import statement can be written together with the export statement
export { foo, bar } from 'my_module'; // It can be simply understood as import { foo, bar } from 'my_module'; export { foo, bar };
Similarly, it can be used with as and *
3, Usage scenario
Nowadays, ES6 modularization has gone deep into our daily project development, such as vue and react project construction projects. Component development can be seen everywhere, and it also depends on modular implementation
vue component
<template> <div class="App"> Component development ---- modularization </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>
react component
function App() { return ( <div className="App"> Component development ---- modularization </div> ); } export default App;
Including the completion of some complex applications, we can also be divided into various modules