CommonJS规范是Node.js遵循的规范。
1. 标识符require为一个全局函数,它仅有一个参数为字符串,该字符串须遵守Module Identifiers的六点规定。
2. require方法返回指定的模块API
3. 如果存在依赖的其他模块,那么依次加载
4. require不能返回,则抛出异常
5. 仅能使用标示符exports导出API
eg:
假定需要加载数学模块并调用相关方法。
var math = require('math');
math.add(2,3);
//5
由于Node.js是服务器环境,其参照CommonJS.js的模块系统也就是服务器端的模块系统。JavaScript程序如何在客户端进行模块化地组织值得思考,最好服务器模块和和客户端模块两者实现兼容,一个模块不用修改,在服务器和浏览器都可以运行。CommonJS规范也想统一前后端写法。
但在客户端有一个很大的局限使得CommonJS规范不适用于浏览器环境。
还是相同的代码,如果在客户端运行
var math = require('math');
math.add(2,3);
//5
math.add(2,3)在第一行
require('math')之后才运行,因此add操作必须等math.js加载完成后才能成功运行。
如果math.js的加载时间很长,整个应用就会停在那里。
这在服务器端不是一个问题,因为所有的模块都存放在本地磁盘,同步加载时,等待的时间也就是硬盘的读取时间。但对于浏览器来说,所有的文件都存放在服务器端,等待时间取决于网速,浏览器可能会处于假死状态。
因此,客户端的模块,不能采用“同步加载”(synchronous),只能采用“异步加载”(asynchronous)。这就是AMD诞生的背景。
AMD(Asynchronous Module Definition)全称为异步模块定义。从名称上看便知它是适合script tag的。它采用异步的方式加载模块,模块的加载不影响它后面语句的运行。也可以说是AMD规范是专门为浏览器中的JavaScript环境设计的规范。它吸取了CommonJS的一些优点,但又不照搬它的格式。开始AMD作为CommonJS的transport format存在,后来因无法与CommonJS开发者达成一致而独立出来。
AMD设计出一个简洁的写模块API:
define(id?, dependencies?, factory);
其中:
id:模块标识,可以省略。
dependencies:所依赖的模块,可以省略。
factory:模块的实现,或者一个JavaScript对象。
特别指出,id遵循CommonJS Module Identifiers。dependencies元素的顺序和factory参数一一对应。
AMD的优点是:适合在浏览器环境中异步加载;可以并行加载多个模块。
缺点是:提高了开发成本,代码的阅读和书写比较困难;不符合通用的模块化思维方式,是一种妥协的实现。
CMD(Common Module Definition)和AMD很相似,尽量保持简单。它与Node.js的Module规范和CommonJS保持了很大的兼容性。
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
CMD的优点:依赖就近,延迟执行;很容易在Node.js中运行。