CommonJS
场景
非浏览起-同步
API
-
module.exports
:导出模块 -
exports
:是module.exports的引用,建议在单一文件中做导出时只使用两者其一,主要是担心手误互相覆盖。 -
require
:导入模块
特点:
-
输出module.exports可以得知他本身是个对象,所以CommonJS导出的内容只能包含在一个对象中
-
// index.js console.log(module); // 输出 { id: ‘/Users/x/Documents/code/demo/index.js‘, exports: {}, parent: { module }, // 调用该模块的模块,可以根据该属性查找调用链 filename: ‘/Users/x/Documents/code/demo/index.js‘, loaded: false, children: [...], paths: [...] }
-
- 导出的内容是值拷贝
-
// 值拷贝 vs 引用 // CommonJS 值拷贝 let a = 1; exports.a = a; exports.add = () => { a++; }; const { add, a } = require(‘./a.js‘); add(); console.log(a); // 1 // ES6 引用 export const a = 1; export const add = () => { a++; }; import { a, add } from ‘./a.js‘; add(); console.log(a); // 2
ES6
场景
浏览器-异步
API
-
export
:导出模块 -
default export
:默认导出的模块 -
import
:导入模块
特点
-
ES6模块的加载是通过
静态解析
(说实话我不懂?),下面附上网上的一段解释:静态解析,什么是的静态解析呢?区别于 CommonJS 的模块实现,ES6 的模块并不是一个对象,而只是代码集合。也就是说,ES6 不需要和 CommonJS 一样,需要把整个文件加载进去,形成一个对象之后,才能知道自己有什么,而是在编写代码的过程中,代码是什么,它就是什么。
-
导出的内容是引用,回顾上面值拷贝拷贝的示例
-
相对于commonJS只能导出对象,ES6模块系统可以任意类型(至少我还没有碰到不能导出的类型)
commonJS与ES6 区别
PS:
- 目前各个浏览器、node.js 端对 ES6 的模块化支持实际上并不友好,更多实践同志们有兴趣可以自己搞一波。
- 在 ES6 中使用 require 字样,静态解析的能力将会丢失!
AMD/CMD
场景:
两者都是用于浏览器异步场景
依赖方式
- AMD是依赖前置:当模块被加载就会执行
- CDM是就近依赖:当模块接在是不会被执行,碰到require时才会被执行
-
定义方式
通过下面代码也可以查看出前面提到依赖方式的差异
AMD
// hello.js define(function() { console.log(‘hello init‘); return { getMessage: function() { return ‘hello‘; } }; }); // world.js define(function() { console.log(‘world init‘); }); // main define([‘./hello.js‘, ‘./world.js‘], function(hello) { return { sayHello: function() { console.log(hello.getMessage()); } }; }); // 输出 // hello init // world init
CMD
// hello.js define(function(require, exports) { console.log(‘hello init‘); exports.getMessage = function() { return ‘hello‘; }; }); // world.js define(function(require, exports) { console.log(‘world init‘); exports.getMessage = function() { return ‘world‘; }; }); // main define(function(require) { var message; if (true) { message = require(‘./hello‘).getMessage(); } else { message = require(‘./world‘).getMessage(); } }); // 输出 // hello init
结论
CMD 的输出结果中,没有打印"world init"。但是,需要注意的是,CMD 没有打印"world init"并是不 world.js 文件没有加载。AMD 与 CMD 都是在页面初始化时加载完成所有模块,唯一的区别就是就近依赖是当模块被 require 时才会触发执行。
参考: https://juejin.im/post/6844903717947310093#heading-4