AMD、CMD、CommonJS和ES Module的理解

1,661 阅读3分钟

通过本文可以了解前端模块体系发展历程中的一些实现规范,注意认真阅读本文中的一些参考链接。

AMD

AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。

define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
    a.doSomething()
    // 此处略去 100b.doSomething()
    ...
})

AMD官方文档

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区别:

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行,RequireJS 2.0也支持延迟执行了。
  2. AMD 推崇依赖前置,CMD 推崇依赖就近。
  3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。

CMD官方文档AMD和CMD区别

CommonJS

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'}
  1. module.exports导出接口,实际是导出一个对象,可以解构
  2. require导入模块会执行并缓存,再次导入会读取缓存

ESModule

阮一峰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和普通导出组合导入
  1. export导出的接口与其对应的值是动态绑定关系,可以获取实时的值
  2. import是编译阶段执行,具有变量提升效果,导入的是模块接口
  3. import()是动态导入,返回的promise的结果是export导出的模块接口

CommonJS与ESModule的区别:

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口(静态加载)。
  3. CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
  4. CommonJS 模块的顶层this指向当前模块,ES6 模块之中,顶层的this指向undefined。
  5. 循环加载时,CommonJS会返回已经执行的部分的值,是ES6 模块是动态引用,加载变量会保存一个模块的引用。

总结

AMD 和 CMD 简单了解其原理即可,CommonJS 与 ES Module 要熟练掌握。