在JavaScript模块化开发中,为了让同一个模块可以运行在前后端,以及兼容多种模块规范(AMD,CMD,Node),类库开发者需要将类库代码包装在一个闭包内。
AMD规范
AMD,即“异步模块定义”。主要实现比如: RequireJS。
其模块引用方式如下:
js 代码:
define(id?,dependencies?,factory);
其中,id及依赖是可选的。其与CommonJS方式相似的地方在于factory的内容就是实际代码的内容,下面是一个简单的例子:
js 代码:
define(function(){ var exports = {}; exports.say = function(){ alert('hello'); }; return exports; });
CMD规范
CMD规范,与AMD类似,区别主要在于定义模块和依赖引入的地方。主要实现比如: SeaJS。
主要区别是:AMD需要在声明模块时指定所有的依赖,通过形参传递依赖到模块内容中。
js 代码:
define(['dep1','dep2'],function(dep1,dep2){ return function(){}; });
与AMD相比,CMD更接近Node对CommonJS规范的定义:
js 代码:
define(factory);
在依赖部分,CMD支持动态引入,如下:
js 代码:
define(function(require,exports,module){ // Todo });
require、exports、module通过形参传递给模块,在需要依赖模块时,随时调用require引入即可。
CommonJS的模块实现
CommonJS的模块引用使用require,如下:
js 代码:
var http = require('http');
Node的模块实现
在Node中引入模块,需要经过下面3个步骤:路径分析;文件定位;编译执行。主要用require()方法来查找模块。
兼容多种模块规范
为了让同一个模块可以运行在前后端,在开发过程中需要考虑兼容前后端问题,以下代码演示如何将hello()方法定义到不同的运行环境中,它能够兼容AMD、CMD、Node以及常见的浏览器环境中:
js 代码:
;(function (name, definition) { // 检测上下文环境是否为AMD或CMD var hasDefine = typeof define === 'function', // 检查上下文环境是否为Node hasExports = typeof module !== 'undefined' && module.exports; if (hasDefine) { // AMD环境或CMD环境 define(definition); } else if (hasExports) { // 定义为普通Node模块 module.exports = definition(); } else { // 将模块的执行结果挂在window变量中,在浏览器中this指向window对象 this[name] = definition(); } })('hello', function () { var hello = function () {}; return hello; });
以上信息主要摘自书籍《深入浅出Nodejs》