一、语法运行方式
CommonJs模块的require是同步加载模块,
- require命令加载某个模块时,会运行整个代码。
- require加载同一个模块时,将会读取缓存
ES6模块的import是异步加载模块
二、加载方式
CommonJS模块是运行时加载
以下代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
ES6模块是编译时输出接口
以下代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。ES6的import会提升至开头
import { stat, exists, readFile } from 'fs';
三、输出值的区别
CommonJS模块化:对输出值的复制
//exCommon.js
let count = 1;
function incCount() {
count++;
}
module.exports = {
count,
incCount
}
//useCommon.js
const C_mdu = require('./exCommon');
console.log(C_mdu.count);//1
C_mdu.incCount();
console.log(C_mdu.count);//1
- 对于基本数据类型,为直接复制,即模块中值再发生改变不影响已引入模块值
- 对于引用类型,为浅拷贝,因与模块中值为一个指针,即值互相影响
ES6模块化:对值的引用 【动态只读引用】
//exES.js
let count = 1;
function incCount() {
count++;
}
module.exports = {
count,
incCount
}
//useES.js
import * as ES_mdu from './exES.js';
console.log(ES_mdu.count);//1
ES_mdu.incCount();
console.log(ES_mdu.count);//2
- 对于只读,import命令将会生成一个只读引用,不可在模块外修改
- 对于动态,原始值发生改变时,import加载的值一样会发生改变
四、循环加载
案例文章 - CSDN - commonjs和ES6及requirejs模块循环引用
CommonJs : 循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ES6:循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
五、使用方法
CommonJs
module.exports 和exports俩者无区别,exports为node简化语法,最终暴露的结果,都是以 module.exports 所指向的对象为准。
exports.xxx,相当于在导出对象上挂属性,该属性对调用模块直接可见
exports =相当于给exports对象重新赋值,调用模块不能访问exports对象及其属性
//exCommon.js
//commonJs模块化 导出
let count = 1;
function incCount() {
count++;
console.log("CommonJs当前计数为:",count);
}
module.exports = {
count,
incCount
}
//useCommon.js
//commonJs模块化 导入
const C_mdu = require('./exCommon');
console.dir(C_mdu);//{ count: 1, incCount: [Function: incCount] }
ES6
//exES.js
//ES6模块化 导出方法一
export let count = 1;
export function incCount() {
count++;
console.log("ES6,当前计数为:" + count);
}
//useES.js
//ES6模块化 导入方法一
import { count, incCount } from "./exES.js";
//ES6模块化 导入方法二 as起别名
import * as ES_mdu from "./exES.js";
console.dir(ES_mdu);//{ count: 1, incCount: [Function: incCount] }
es6使用export default
// 如果一个js模块文件就只有一个功能, 那么就可以使用export default导出
// 一个模块不能具有多个默认导出
// 暴露.js
export default {
name: 'xiaoming',
age: 18
};
// 引用.js
import person from '暴露.js'