AMD&CMD规范
JS模块化编程
随着前端开发的不断发展,互联网业务的复杂度越来越高,JS模块化开发已经变得越来越重要。
我们在前端开发过程中,使用统一的编写方式进行模块化,可以对巨大系统和复杂业务的代码进行很好的组织和管理,方便多人的合作。
JS中的模块化规范包括(CommonJS, AMD, CMD)。
(1)CommonJS
CommonJS是一个有志于构建Javascript生态圈的组织。整个社区致力于提高javascript程序的可移植性和可交换性,无论是在服务端还是浏览器端。
a group with a goal of building up the javascript ecosystem for web browsers, desktop and command line apps and in the browser.
CommonJS是一个更偏向于服务器端的规范。Node.js采用了这个规范。根据CommonJS规范,一个单独的文件就是一个模块。
CommonJS规范的主要内容:模块必须通过module.exports导出对应的变量或接口,通过require()导入其他模块的输出到当前模块。
// moduleA.js
module.exports = function(value) {
return value++;
}
// moduleB.js
var moduleA = require('./moduleA');
var result = moduleA(2);
优点
* 便于服务器端重用
* NPM中已经提供近20W个模块包
* 简单并容易使用
缺点
* 使用同步的方式加载资源,阻塞加载,不适合在浏览器环境中使用。
* 不能非阻塞的并行加载多个模块
(2)AMD规范
AMD(Asynchronous Module Definition 异步模块定义)。它采用异步方式加载模块,模块的加载不影响后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到依赖模块全部加载完成后,再执行这个回调函数。
简单地说:异步模块定义就是 依赖前置, 所有的require都被提前了。RequireJS就是AMD规范的实现
define()函数
example:
define('alpha',['require', 'exports', 'beta'], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
}
})
AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:
require([dependencies],callback);
第一个参数[dependencies],是一个数组,代表依赖的模块; 第二个参数callback,则是依赖模块加载成功后,执行的回调函数。
example:
require(['math'], function(math) {
math.add(1, 2);
})
优点
* 适合在浏览器环境异步加载
* 并行加载多个模块
缺点
* 开发体验和阅读不友好
(3)CMD规范
CMD(Common Module Definition 通用模块定义)。它更贴近CommonJS Modules、1.1和Node Modules规范,一个模块就是一个文件。
简单来说就是:
1. **通过exports暴露接口**
2. **通过require引入依赖**
它推崇依赖就近,即想什么时候加载就什么时候require,实现了 懒加载, 延迟执行。SeaJS是CMD规范的实现。
example:
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSth = ...;
module.exports = ...;
})
上例中同时使用了exports和module.exports,传入factory构造方法的参数exports是module.exports对象的一个引用。
exports和module.exports的关系
1. module.exports初始值为一个空对象{}, 所以exports的初始值也是一个{};
2. exports是module.exports的一个引用,他们指向同一块内存;
3. require() 返回的是module.exports而不是exports;