通过本文可以了解前端模块体系发展历程中的一些实现规范,注意认真阅读本文中的一些参考链接。
AMD
AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
CMD
CMD---是SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架。
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
var b = require('./b') // 依赖可以就近书写
b.doSomething()
})
AMD和CMD区别:
- 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行,RequireJS 2.0也支持延迟执行了。
- AMD 推崇依赖前置,CMD 推崇依赖就近。
- AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。
CommonJS
Node 应用由模块组成,采用 CommonJS 模块规范。每个文件都是一个模块,用module变量表示,通过module.exports对外输出一个对象,通过require加载模块。
// a.js
exports.hello = function() {
return 'hello';
};
module.exports.text = 'Hello world';
// b.js
var a = require('./a.js'); // {hello: function.., text: 'Hello world'}
- module.exports导出接口,实际是导出一个对象,可以解构
- require导入模块会执行并缓存,再次导入会读取缓存
ESModule
ES6 在语言标准的层面上,实现了模块功能ESModule,完全可以取代 AMD 和 CommonJS 规范,成为浏览器和服务器通用的模块解决方案。
// 导出 a.js
export const year = 1958;
export function getYear(){}
const name = '剑豪'
function getNmae (){}
export { name, getNmae }
const obj = {name: '剑豪'}
export default obj
export default funcion foo(){} // 视作导出匿名函数
// 导入 b.js
import { name, getName } from './a'
import { name: newName, getName } from './a' // 报错,import导入不能这样重命名,只能使用 as
import { name as newName, getName } from './a' // 正确
import * as obj from './a'
const { a, getName } = obj
import a, {name, getName} from './a' // default和普通导出组合导入
- export导出的接口与其对应的值是动态绑定关系,可以获取实时的值
- import是编译阶段执行,具有变量提升效果,导入的是模块接口
- import()是动态导入,返回的promise的结果是export导出的模块接口
CommonJS与ESModule的区别:
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口(静态加载)。
- CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
- CommonJS 模块的顶层this指向当前模块,ES6 模块之中,顶层的this指向undefined。
- 循环加载时,CommonJS会返回已经执行的部分的值,是ES6 模块是动态引用,加载变量会保存一个模块的引用。
总结
AMD 和 CMD 简单了解其原理即可,CommonJS 与 ES Module 要熟练掌握。