commonJS,AMD与CMD的区别与联系

commonJS,AMD与CMD的区别与联系

1. CommonJS原本叫serverJS,是以在浏览器环境之外构建JavaScript生态环境为目标而产生的项目,比如在服务器和桌面环境中。

commonJS规范是为了解决JavaScript的作用于问题而定义的模块形式,可以使每个模块在它自身的命名空间中执行。

该规范的主要内容是,模块必须通过module.exports导出对外的变量或接口,通过require()来导入其它模块的输出到当前模块作用域中。Node.js就是采用commonJS规范。

1
2
3
4
5
6
7
8
//moduleA.js
module.exports = function(){
console.log('hello');
}
//moduleB.js
var moduleA = require('./moduleA');
moduleA();

2.AMD(Asynchronous Module Definition)(异步模块定义)是为了浏览器环境设计的,因为CommonJS模块系统是同步加载的,当前浏览器环境是异步的。

AMD定义了一套JavaScript模块依赖异步加载标准,来解决同步加载问题。

模块通过define函数定义在闭包中,格式如下

define(id? String, dependencies? String[], factory: Function|Object)

  • id是模块名字,它是可选参数

  • dependencies 指定了所要依赖的模块列表,他是一个数组,也是可选的参数,每个依赖的模块的输出将作为参数一次传入factory中。如果没有指定dependencies,那么他的默认值是[‘require’,’exports’,’module’]

  • factory 是最后一个参数,它包裹了模块的具体实现,他是一个函数或是一个对象。如果是函数,那么它的返回值就是模块的的输出接口或值。

定义一个moduleA,它依赖jQuery模块

1
2
3
4
5
6
define('moduleA',['jquery'],function($){
//$是jquery模块输出
$('body').text('hello');
});
//使用
define(['moduleA'],function(moduleA){});

require.js就是采用AMD模块

3.CMD(Common Module Defination)

在cmd规范中,一个模块就是一个文件。代码的书写格式如下:define(factory)
define是全局函数,用来定义模块。define接受factory参数,factory可以是函数,对象或字符串。

  • 当factory为对象或字符串时,表示该模块的接口就是该对象或字符串,比如要定义一个json数据模块
    define({‘key’,’value’})

  • 也可以通过字符串定义模板模块 define(‘Hello ‘)

  • factory是函数时,表示是模块的构造方法。执行该构造方法,可以得到模块对外提供的接口,factory方法在执行时,默认会传入三个参数,require,exports,module

1
2
3
define(function(require,exports,module){
//需要导出的模块
});

require是方法,接收模板标识作为唯一参数,用来获取其它模块提供的接口

1
2
3
4
define(function(require, exports){
const a = require('./a');
a.doSomething();
});
  • require是同步往下执行的,require.async(id,callback?)用来在模块内部异步加载模块,并在加载完后执行回调函数。
1
2
3
4
5
6
define(function(require, exports){
require.async(['./a,'./b], function(c ,d ){
c.doSomething();
d.doSomething();
});
});
  • factory是函数时的第二个参数是exports,exports是一个对象,用来对外提供模块接口
1
2
3
4
5
6
define(function(require, exports){
exports.str = 'xxxxxxxxx';
exports.doSomething = function(){ //对外提供doSomething方法
}
});

除了exports外,还可以用return直接对外提供对象接口

1
2
3
4
5
6
7
8
define(function(require, exports){
return{
str: 'xxxxxxx',
doSomething: function(){
}
}
});

exports是module.exports对象的一个引用,很多时候exports都无法满足需求,列如对外提供一个实例对象

1
2
3
4
5
6
7
8
define(function(require, exports,module){
function Person(name, age){
this.name = name;
this.age = age;
}
module.exports = new Person('lily',34);
});

AMD与CMD比较

AMD默认是依赖前置,在一开始就将需要依赖的文件配置并加载好

1
2
3
4
define('moduleA',['jquery'],function($){
//依赖的配置文件已经配置并加载好了
$('body').text('hello world');
});

CMD是依赖就近,需要使用的时候才会去配置加载

1
2
3
4
5
6
define(function(require, exports){
var a = require('./a.js'); //配置并加载,同步
if(false){
var b = require('./b.js'); //配置的文件永远不会被加载
}
});