AMD
Asynchronous Module Definition,意思是异步模块定义。
用法:
1
2
3
4
|
// 定义模块
define(id?, dependencies?, factory)
// 引用模块
require([module], callback)
|
对于依赖的模块 AMD 是提前执行,代表是 RequireJS
例子:
1
2
3
4
5
|
define(["./a", "./b"], function(a, b) {
// 依赖一开始就写好
a.test();
b.test();
});
|
CMD
CMD 即 Common Module Definition 通用模块定义。
用法:
1
|
define(id?, deps?, factory(require, exports, module){})
|
例子:
对于依赖的模块 CMD 是延迟执行,代表是 SeaJS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
define(function (requie, exports, module) {
//依赖可以就近书写
var a = require('./a');
a.test();
...
//软依赖
if (status) {
var b = requie('./b');
b.test();
}
});
|
AMD 和 CMD 的区别
最明显的区别就是在模块定义时对依赖的处理不同
- AMD 推崇依赖前置,在定义模块的时候就要声明其依赖的模块
- CMD 推崇就近依赖,只有在用到某个模块时再去 require
最大的区别是对依赖模块的执行时机处理不同(都是异步加载)
CommonJS
CommonJS 运行时加载,引入的是值的拷贝,加载一次之后就会缓存到内存中
运行时加载
1
2
|
var file = "./a.js";
var A = require(file);
|
引入的是值的拷贝
1
2
3
4
5
6
7
8
|
// a.js
var counter = 0;
var add = () => {
counter++;
};
exports.counter = counter;
exports.add = add;
|
1
2
3
4
5
|
// b.js
var a = require("./a.js");
console.log(a.counter); // 0
a.add();
console.log(a.counter); // 0
|
缓存到内存
CommonJS 的一个模块,就是一个脚本文件。require 命令第一次加载脚本,就会执行整个脚本,然后在内存生成一个对象
1
2
3
4
5
6
|
{
id: '...', // 模块名
exports: {...}, // 模块输出的各个接口
loaded: true // 模块的脚本是否执行完毕
...
}
|
再次 require,也不会再次执行该模块,而是到缓存中取值。
ES6 Module
ES6 Module 是编译时加载(静态解析),引入的是值的引用
编译时加载
1
2
|
// ES6模块,只引入了stat, exists, readFile三个模块,其他方法不加载
import { stat, exists, readFile } from "fs";
|
引入的是值的引用
1
2
3
4
5
|
// a.mjs
export var name = 1;
export function changeName(val) {
name = val;
}
|
1
2
3
4
5
6
|
// b.mjs
import { name, changeName } from "./es6_a.mjs";
console.log(name); // 1
changeName("haha");
console.log(name); // haha
|
es6 模块与 CommonJS 模块的差异
两个重大差异:
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时加载(编译时输出接口)
第二个差异是因为 CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
参考
- Module 的加载实现
- 前端模块化,AMD 与 CMD 的区别