模块化思想在前端的应用层出不穷,它的出现也加快了前端内容的开发,和下部的复用,同时增加了合作性。做到模块化,就要有一定的模块规范, CommonJS为后端定制了特定的规范,但是鉴于网络的原因,CommonJS并不完全适合前端的应用场景,经过一段时间争论后,AMD(Asynchronous Module Definition,异步模块定义)规范最终在前端应用场景中胜出。除此之外,还有国内玉伯的CMD。
1.AMD规范
AMD规范是CommonJS模块规范的一个延伸,它的模块定义如下:
define(id?,dependencies?,factory);
它的模块id和依赖都是可选的,与node模块相似的地方在于factory的内容就是实际代码中内容。下面的代码定义了一个简单的模块:
define(function(){
var exports = {};
exports.sayHello=function(){
alert('hello from module:' + module.id);
}
return exports;
})
不同的地方就是AMD模块需要用define来明确定义一个模块,而Node实现中是隐式包装的,他们的目的都是作用域隔离(不知道啥是作用域隔离,去问度娘或者谷妹吧),仅在需要的时候被引入,避免掉过去那种通过全局变量或者全局命名空间的方式,以免变量污染和不小心被修改。另一个区别就是内容通过返回的方式实现导出。例如require.js的实现方式
2 CMD规范
它与AMD规范的主要区别在于定义模块和依赖引入的部分,AMD需要在声明模块的时候制定所有的依赖,通过形式参数传递依赖到模块内容中:
define(['dep1','dep2'],function(dep1,dep2)){
return function(){};
});
而CMD模块更接近于Node对CommonJS规范的定义:
define(factory);
在依赖部分,CMD支持动态引入,示例如下:
define(function(require,exports,module){
//这里来写模块内容
})
require、exports和module通过形式参数传递给模块,在需要依赖模块时,随时调用require()引入即可。例如sea.js的实现方式
3.兼容多种模块规范的写法
前面废话那么多,现在为了让同一个模块可以运行在前后端,在写作过程中需要考虑兼容前端也实现模块规范的环境。为了保持前后端的一致性,类库开发者需要将类库代码包装在一个闭包内。下面栗子演示如何将hello方法定义到不同的运行环境中,兼容Node、AMD、CMD以及常见的浏览器环境中:(用的时候copy一下就ok了)
```
;(function(name,definition){
//检测上下文环境是否为AMD或者CMD
var hasDefine=typeof define==='function',
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)!
```
```
网友评论