我的笔记: 前端模块化のCommonJS,AMD,CMD,ES6 Module

315 阅读3分钟

模块化开发能提高代码复用率,方便代码管理。

CommonJS

  • 主要用于服务器端,例如 Node
  • 用module.exports定义当前模块对外输出的接口,用require加载模块。
    • require参数:
      • 引用核心模块时,不需要写路径,直接写需引用的模块名即可
      • 引用自定义的模块时,参数需写路径,可省略.js

// 暴露模块
module.exports = {
  plus,
  minus,
}
// 或使用exports, 相当于var exports = module.exports;
// 注意:不能直接给exports赋值;如果给module.exports赋值后,exports也会失效。
exports.plus = plus;
exports.minus = minus;

// 引用模块
var a = require('./a');

ES6 Module

  • ES6 在语言标准的层面上,实现了模块功能。
  • 主要由两个命令构成:export和import
    • export命令用于规定模块的对外接口
    • import命令用于输入其他模块提供的功能。
// 暴露模块
export var a = 1;
export var b = 2;
// or
export { a, b };
// or
export default { a, b }

// 引用模块
import { a, b } from './a';

CommonJS 和 ES6 Module对比

  • CommonJS 模块输出的是值的拷贝,ES6 模块输出的是值的引用
    • CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
    • ES6 模块输出的是值的引用,模块里面的内容如果发生变化,输出的内容也会随之改变。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
    • 运行时加载:
      • CommonJS模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
    • 编译时加载:
      • ES6 模块不是对象,而是通过 export命令显式指定输出的代码,import时采用静态命令的形式。即在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”。

AMD

AMD是requireJS在推广过程中对模块定义的规范化的产出:它采用异步方式加载模块,模块的加载不影响它后面语句运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行
简单说AMD是提前执行(异步加载:依赖先执行)+延迟执行

  • 主要用于浏览器环境,RequireJS的产出
  • 推崇依赖前置,在定义模块的时候就要声明其依赖的模块;
define(['./a', './b'], function (a, b) {
  a.doSomething()
  // 此处略去 100 行
  b.doSomething()
  // ...
})

CMD

延迟执行(运行到需加载,根据顺序执行)

  • 主要用于浏览器环境, SeaJS的产出
  • 推崇依赖就近,只有在用到某个模块的时候再去require
  • 在 CMD 规范中,一个模块就是一个文件
define(function (require, exports, module) {
  var a = require('./a')
  a.doSomething()
  // 此处略去 100 行
  var b = require('./b') 
  b.doSomething()
  // ...
})

AMD 和 CMD对比

  • AMD:在最开始声明依赖模块,加载模块后马上运行模块化内代码,不管回调函数是否要用到相关模块
  • CMD:在需要时声明依赖模块、加载模块

参考1 参考2 参考3