共计 4096 个字符,预计需要花费 11 分钟才能阅读完成。
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.exports
与 require
指向的是同一块内存地址,任何一方扭转都会影响另一方的数据(动静)
案例一:
// 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=1
b 模块已接收数据:aNum=1,aArr=1
1s a 模块扭转数据 aNum&aArr:
aNum=11,module.exports.aNum=1
aArr=1,11,module.exports.aArr=1,11
2s b 模块承受数据:aNum=1,aArr=1,11
2s b 模块扭转数据:aNum=2,aArr=2
3s 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.mjs
export 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=1
b 模块已接收数据:aNum=1,aArr=1
1s a 模块扭转数据 aNum&aArr:
aNum=11
aArr=1,11
2s b 模块承受数据:aNum=11,aArr=1,11
2、export default
有点非凡,导出的数据要依据数据类型来定,与 CommonJS 的 module.exports
有点相似
// es6_a.mjs
let 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.mjs
import 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=1
b 模块已接收数据:aNum=1,aArr=1
1s a 模块扭转数据 aNum&aArr:
aNum=11
aArr=1,11
2s b 模块承受数据:aNum=1,aArr=1,11
3、* 在 export * from 'xxx'
前面加正文会报怪异的 bug,导出的数据为undefined
import
1、导入 default
的不须要应用{}
,导入非默认模块则须要加{}
2、一个文件能够同时导出默认的模块和非默认的模块,如下所示:
// es6_a.mjs
export 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);
// 输入后果
3
red
3、能够应用 as
在导出和导入时重命名
// es6_a.mjs
function sum(num1, num2) {return num1 + num2;}
export {sum as a};
// es6_b.mjs
import {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