CommonJS 和 ES6 Module
CommonJS
主要用在服务器端,Node.js 目前使用的规范,使用 module.exports 或者 exports 导出,require 引入。
为了避免出问题,我们一般使用 module.exports(本质是一个对象)来导出,因为 exports 是对 module.exports 的引用。当你的 exports 的引用对象不再指向 exports 时,导出就会出现问题
基本的用法
export_test.js
let a = 100;
let b = [1, 2, 3];
let c = {
name: 'lee',
age: 25
};
function add(a, b) {
return a + b;
}
module.exports = {
a,
b,
c,
add
}
import_test.js
const obj = require('./export_test.js');
console.log(obj.add(2, 3)); // 5
console.log(obj.a); // 100
使用 exports
这里使用 exports 的话就要改变一下写法了,前面说过 exports 是对 module.exports 的一个引用,你最终导出的还是 module.exports,而不是说你写 exports 导出的就是 exports。所以建议在使用时尽量使用 module.exports。
下面这种写法会报错
这个基于上面 export_test.js 的内容来说的
// exports 的指向变成了一个包含 a,b,c,add 的对象,但是 CommonJS 默认导出的是 module.exports,所以 require 过后也取不到 a,b,c,add 这些。
exports = {
a,
b,
c,
add
}
正确的写法
exports.a = a;
exports.b = b;
exports.c = c;
exports.add = add;
三种正确的导出方法
// 三种导出方法,取其中一个即可
/* 第一种导出方法 */
module.exports = {
a,
b,
c,
add
}
/* 第二种导出方法 */
module.exports.a = a;
module.exports.b = b;
module.exports.c = c;
module.exports.add = add;
/* 第三种导出方法 */
exports.a = a;
exports.b = b;
exports.c = c;
exports.add = add;
其它注意点
- 混合使用
// 混合使用
exports.a = a;
exports.b = b;
module.exports.c = c;
module.exports.add = add;
这样也是可以的。
特点
CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。像 Node.js 主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式,所以 CommonJS 规范比较适用。
ES6 Module
ES6 Module 是 ES6 提出来的标准,使用 export 或者 export default 来导出,使用 import 来导入。node.js 从 13.2.0 过后开始支持 ES Module 了,不过需要把你的 js 文件命名为 mjs,或者在你的项目的 package.json 中声明 "type": "module"
,我这儿为了方便,更新了 node.js 为 13.5.0,同时文件后缀为 mjs。
基础用法
export_test.mjs
let a = 100;
let b = [1, 2, 3];
let c = {
name: 'lee',
age: 25
};
function add(a, b) {
return a + b;
}
export {a, b, c, add};
import_test.mjs
import { a, b, c, add } from './export_test.mjs';
console.log(a); // 100
console.log(b); // [1, 2, 3]
console.log(c); // {name: 'lee',age: 25}
console.log(add(2, 3)); // 5
注:使用上面的 export 导出对象时,另一个模块的 import 的花括号里面的变量名必须跟导出模块里面的变量名相同,不然会报错,变量的书写次序可以不同。
使用 export default
把 export_test.mjs 的导出语句写成这种
export default {a, b, c, add};
然后呢修改 import_test.mjs 的引入语句
import Test from './export_test.mjs';
console.log(Test.a); // 100
console.log(Test.b); // [1, 2, 3]
console.log(Test.c); // {name: 'lee',age: 25}
console.log(Test.add(2, 3)); // 5
其它用法
注意:一个模块里面 export 语句可以有多个,但是 export default 只能有一个。
多个 export 语句
// 多个 export 语句
export const a = 12;
export function reduce(a, b) {
return a - b;
}
// 注意这样写是不行的
const c = 'hello';
export c;
// 另一个模块导入
import {a, reduce} from './export_test.mjs';
console.log(a);
console.log(reduce(5, 2));
多个 export 语句在另一个模块导入时可以全部封装为一个对象
// 这样也是可以的
import * as Test from './export_test.mjs';
console.log(Test.a);
console.log(Test.reduce(5, 2));
export default 注意事项
// 这样写莫得问题,相当于导出一个函数对象
export default function add(a, b) {
return a + b;
}
// 这两种都是错误写法
export default const j = 100;
export default let k = 100;
// 这样写就没问题了
let j = 100;
export default j;
特点
ES6 的模块不是对象,import 命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。
参考资料
AMD, CMD, CommonJS 和 UMD
再次梳理 AMD、CMD、CommonJS、ES6 Module 的区别
前端模块化:CommonJS,AMD,CMD,ES6
import、require、export、module.exports 混合使用详解
Javascript 模块化七日谈
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论