Before, I always looked at the contents of module mechanism class in a casual way. I didn't know one of them. I only knew the superficial knowledge of AMD\CMD\Common.js. Today, I saw a big guy's article, which is very good in summary. It's convenient to look up it after taking a note.
Mainstream module specification
1. UMD
2. CommonJs
3. es6 module
1. umd module (general module)
(function (global,factory){ typeof exports ==='object'&&typeof module !=='undefined'?module.exports=factory() typeof define==='function'&& define.amd ? define(factory):(global.libName=factory()) }(this,(function(){'use strict'})));
If you see such code in the header of js file, the file uses UMD specification, which is actually a combination of amd+commonjs + global variables.
This code is the judgment of the current running environment. If it is Node environment, it uses CommonJs specification. If it is not, it determines whether it is AMD environment. Finally, it exports global variables
With UMD, our code runs on Node and browser at the same time, so most front-end libraries use UMD specification at the end of packaging
2. CommonJs
The module system used in NodeJs environment is based on the CommonJs specification. Now, the CommonJs specification mostly refers to the module system of Node.1, Module export
Keywords: module.exports exports
//foo.js // Export by export module.exports.age=1 module.exports.foo=function(){} exports.a='hello' //Whole export module.exports={age:1,a:'hello',foo:function(){}} //Cannot use 'exports' for overall export. Cannot use' exports' for import exports={age:1,a:'hello',foo:function(){}}
It should be noted that exports cannot be assigned. It can be understood that exports=module.exports before the module starts, because exports lose the module after the assignment. References to exports become local variables within a module
2, Module import
Keyword: require
const foo=require('./foo.js') console.log(foo.age)//1
3, Recycling
//a.js module.exports.a=1 var b=require('./b') console.log(b) module.exports.a=2 //b.js module.exports.b=11 var a=require('./a') console.log(a) module.exports.b=22 //main.js var a=require('./a') console.log(a)
3. ES6 module
Before ES6, javascript did not belong to its own module specification, so the community formulated the commonjs specification. Node borrowed ideas from the commonjs specification, so there was node's module, and AMD asynchronous module was also born from the commonjs specification, and then there was require.js running on the browseres6 module basic syntax:
export
export * from 'module'; export {name1,name2,....,nameN } from 'module';//Redirect named exports export {import1 as name1,import2 as name2,...,nameN } from 'module'; //Redirect rename export export {name1,name2,..,nameN};//Bind named exports with previously declared variable names export let name1='name1';//Declare named exports or var,const,function,function*,class export default expression;//Default export export default function(){...}//Or function*,class export default function name1(){...}//Or function*,class export { name1 as default,...};//Rename to default export
import
//Named export module.js let a=1,b=2 export {a,b} export let c=3 //Named import main.js import {a,b,c} from 'module';//a:1 b:2 c:3 import {a as newA,b,c as newC } from 'module';//newA:1 b:2 newC:3 // Export module.js by default export default 1 // Import main.js by default import defaultExport from 'module';//defaultExport:1 // Mixed export module.js let a=1 export {a} const b=2 export {b} export let c=3 export default [1,2,3] // module.js Array.prototype.remove=function(){} //Side effects only run one module import 'module';//Execute module without exporting value multiple times call module.js only once //Dynamic import (asynchronous import) var promise=import('module');
Features of ES6 module
1. The syntax of ES6 module is static
- import is automatically promoted to the top level of the code
- export and import can only appear at the top level of the code. The following syntax is wrong
// if for while and so on cannot be used { export let a=1 import defaultExport from 'module' } true || export let a=1
The import name of import cannot be a string or a judgment statement. The following code is wrong
import 'defaultExport' from 'module' let name='Export' import 'default' + name from 'module'
Static syntax means that import and export can be determined at compile time, and dependency can be found more quickly. You can use lint tool to check module dependency, import and export plus type information can be checked statically
2. The export of ES6 module is bound
- Modules imported using import run in strict mode
- The variables imported with import are read-only. It can be understood that the default value is const decoration and cannot be assigned
- The variables imported with import are bound / referenced with the original variables. It can be understood that the imported variables are passed by reference whether they are of basic type or not
//The basic type in js is value passing let a =1 let b=a b=2 console.log(a,b) //1 2 //Reference type in js is reference passing let obj={name:'obj'} let obj2=obj obj2.name="obj2" console.log(obj.name,obj2.name) //obj2 obj2 //Basic types in es6 module are also passed by reference // foo.js export let a=1 export function count(){ a++ } // main.js import {a,count} from './foo' console.log(a)//1 count() console.log(a)//2 // export default is not a dynamic binding, which is similar to CommonJs. It's a copy of value let a=1; export default a // Dynamic binding of default can be implemented in another way let a=1; export {a as default} export function count(){ a++ } // Just like main.js above
The above code is the difference between CommonJs export variable and ES6 export variable
3. Es module circular reference
//bar.js import { foo } from './foo' console.log(foo); export let bar="bar" //foo.js import {bar} from './bar' console.log(bar); export let foo='foo' // main.js import {bar} from './bar' console.log(bar)
1. Execute main.js - > Import bar.js
2. Bar. JS - > Import foo.js
3. Foo.js - > Import bar.js - > bar.js has executed direct return - > output bar - > bar is not defined, bar does not define error reporting
We can use function to solve:
//bar.js import {foo} from './foo' console.log(foo()); export function bar(){ return 'bar' } // foo.js import { bar } from './bar' console.log(bar()); export function foo(){ return 'foo' } //main.js import {bar} from './bar' console.log(bar)
Because the function declaration will prompt to the top of the file, you can directly call the bar method of bar.js that has not been executed in foo.js. Do not use external variables in the function, because variables have not been declared (let,const) and assigned value, var
Difference between CommonJs and ES6 Module
1. CommonJs exports a copy of variables, and ES6 Module exports the binding of variables (export default is special)
2. CommonJs is a single value export, and ES6 Module can export multiple
3. CommonJs is a dynamic syntax that can be written in judgment, while ES6 Module static syntax can only be written in the top level
4. This of CommonJs is the current module, and this of ES6 Module is undefined