CommonJS

前言

NodeJS中应用的模块标准。
依据CommonJS标准,一个独自的文件就是一个模块(module)。加载模块应用require办法,该办法读取一个文件并执行,最初返回文件外部的module.exports对象。
CommonJS采纳同步加载模块的形式,只有加载完能力执行前面的操作,次要实用于服务端。

应用规定

1、exports与require应用的模块导入导出规则遵循的是CommonJS(AMD和CMD)标准, 个别在NodeJS(express,koa)中应用,是绝对比拟先呈现的标准,也是目前大多数浏览器反对的模块导入导出标准。

module.exports 与 exports

1、一个文件即为一个module;
2、一个module中有很多字段,例如 id path parent exports等等,能够间接在js文件输入module即可查看;
3、exports示意这个module要导出的数据,module.export默认指向一个空的对象内存;
4、变量exports默认指向module.exports(援用传递);
5、module实际上导出的数据是在module.export这个变量中;

require

1、应用require即可导入另一模块中导出的数据;

exports与require之间的分割

无论模块exports的是什么数据类型,module.exportsrequire指向的是同一块内存地址,任何一方扭转都会影响另一方的数据(动静)

案例一:

// a.js文件let aNum = 1;let aArr = [1];setTimeout(() => {  aNum = 11; // 并不会影响module.exports.aNum的值  aArr.push(11); // 会影响module.exports.aArr的值  console.log('1s a模块扭转数据aNum&aArr:');  console.log(`aNum=${aNum},module.exports.aNum=${module.exports.aNum}`);  console.log(`aArr=${aArr},module.exports.aArr=${module.exports.aArr}`);}, 1000)setTimeout(() => {  console.log(`3s a模块承受数据:aNum=${module.exports.aNum},aArr=${module.exports.aArr}`);}, 3000)// 以下写法等价于// module.exports.aNum = aNum aNum属于根本类型 值拷贝// module.exports.aArr = aArr aArr属于对象 值援用module.exports = {  aNum,  aArr};console.log(`a模块已导出数据:aNum=${module.exports.aNum},aArr=${module.exports.aArr}`);// b.js文件const a = require("./commonjs_a");console.log(`b模块已接收数据:aNum=${a.aNum},aArr=${a.aArr}`);setTimeout(() => {  console.log(`2s b模块承受数据:aNum=${a.aNum},aArr=${a.aArr}`);  a.aNum = 2;  a.aArr = [2]  console.log(`2s b模块扭转数据:aNum=${a.aNum},aArr=${a.aArr}`);}, 2000)// 输入后果a模块已导出数据:aNum=1,aArr=1b模块已接收数据:aNum=1,aArr=11s a模块扭转数据aNum&aArr:aNum=11,module.exports.aNum=1aArr=1,11,module.exports.aArr=1,112s b模块承受数据:aNum=1,aArr=1,112s b模块扭转数据:aNum=2,aArr=23s a模块承受数据:aNum=2,aArr=2

ES6 Module

前言

应用规定

1、export与import是ES组织官网退出的模块化计划,个别在typescript和三大框架(Angular, Vue, React)中比拟常见,但目前反对这套标准的客户端浏览器比拟少,所以通常状况下代码都要通过Babel转换成目前浏览器能反对的,也就是exports和require那一套。

export 与 export default

1、无论导出数据是什么类型的,export导出的都是变量的援用绑定;

2、任何未显式导出的变量、函数或类都是模块公有的,无奈从模块内部拜访;

// es6_a.mjsexport let aNum = 1;export let aArr = [1];setTimeout(() => {  aNum = 11;  aArr.push(11);  console.log('1s a模块扭转数据aNum&aArr:');  console.log(`aNum=${aNum},`);  console.log(`aArr=${aArr},`);}, 1000)console.log(`a模块已导出数据:aNum=${aNum},aArr=${aArr}`);// es6_b.mjs// import时必须加{ }import {aNum, aArr} from './es6_a.mjs';console.log(`b模块已接收数据:aNum=${aNum},aArr=${aArr}`);setTimeout(() => {  console.log(`2s b模块承受数据:aNum=${aNum},aArr=${aArr}`);}, 2000);// 输入后果a模块已导出数据:aNum=1,aArr=1b模块已接收数据:aNum=1,aArr=11s a模块扭转数据aNum&aArr:aNum=11aArr=1,112s b模块承受数据:aNum=11,aArr=1,11

2、export default有点非凡,导出的数据要依据数据类型来定,与CommonJS的module.exports有点相似

// es6_a.mjslet aNum = 1;let aArr = [1];setTimeout(() => {  aNum = 11;  aArr.push(11);  console.log('1s a模块扭转数据aNum&aArr:');  console.log(`aNum=${aNum}`);  console.log(`aArr=${aArr}`);}, 1000)// 与module.exports相似export default {  aNum, // 数值类型 深拷贝  aArr // 对象类型 浅拷贝}console.log(`a模块已导出数据:aNum=${aNum},aArr=${aArr}`);// es6_b.mjsimport a from './es6_a.mjs';console.log(`b模块已接收数据:aNum=${a.aNum},aArr=${a.aArr}`);setTimeout(() => {  console.log(`2s b模块承受数据:aNum=${a.aNum},aArr=${a.aArr}`);}, 2000);// 输入后果a模块已导出数据:aNum=1,aArr=1b模块已接收数据:aNum=1,aArr=11s a模块扭转数据aNum&aArr:aNum=11aArr=1,112s b模块承受数据:aNum=1,aArr=1,11

3、* 在export * from 'xxx'前面加正文会报怪异的bug,导出的数据为undefined

import

1、导入default的不须要应用{ },导入非默认模块则须要加{ }

2、一个文件能够同时导出默认的模块和非默认的模块,如下所示:

// es6_a.mjsexport let color = 'red';export default function(num1, num2) {  return num1 + num2;}// es6_b.mjs// 默认值必须排在非默认值之前import sum, { color } from  './es6_a.mjs';console.log(sum(1,2));console.log(color);// 输入后果3red

3、能够应用as在导出和导入时重命名

// es6_a.mjsfunction sum(num1, num2) {  return num1 + num2;}export { sum as a };// es6_b.mjsimport { a as aa } from './es6_a.mjs';console.log(aa(1,2));// 输入后果3

两者差别

1. CommonJS 模块输入的是一个值的拷贝(依据数据类型分为深拷贝或浅拷贝),ES6 模块输入的是值的援用(任何数据类型)
CommonJS 模块输入的是值的拷贝,也就是说,一旦输入一个值,模块外部的变动就影响不到这个值。ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本动态剖析的时候,遇到模块加载命令import,就会生成一个只读援用。等到脚本真正执行时,再依据这个只读援用,到被加载的那个模块外面去取值。换句话说,ES6 的import有点像 Unix 零碎的“符号连贯”,原始值变了,import加载的值也会跟着变。因而,ES6 模块是动静援用,并且不会缓存值,模块外面的变量绑定其所在的模块。

2. CommonJS 模块是运行时加载,ES6 模块是编译时输入接口

3. ES6 Module中导入的数据为const,不容许从新赋值;而CommonJS中导入的数据容许从新赋值

参考1