The difference between CommonJs and es6 module

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 browser

es6 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

Published 33 original articles, won praise 4, visited 10000+
Private letter follow

Tags: Javascript

Posted on Fri, 17 Jan 2020 03:31:06 -0500 by foreverdita