浅谈JavaScript模块化规范AMD与CMD

1、模块化

模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理。模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式。模块化使得系统被分解为一组高内聚,低耦合的模块,在理想状态下只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过直接加载被人已经写好模块进行使用即可。

一个模块化系统所必须的能力:

1) 定义封装的模块。

2) 定义新模块对其他模块的依赖。

3) 可对其他模块的引入支持。

 

2、模块化的规范

为了 JavaScript 的模块化开发,特别是在浏览器端的模块化开发,实现了几种规范:

1) AMD,异步模块定义是 RequireJS 在推广过程中对模块定义的规范化产出。

2) CMD,通用模块定义,是 SeaJS 在推广过程中对模块定义的规范化产出。

3) CommonJS,是 BravoJS 在推广过程中对模块定义的规范化产出。

 

3、AMD与RequireJS:

所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中。

AMD规范定义了一个自由变量或者说是全局变量 define 的函数。

语法:define([id], [dependencies], factory);    

1) id:字符串类型,表示模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。如果存在,那么模块标识必须为顶层的或者一个绝对的标识。

2) dependencies:一个当前模块依赖的,已被模块定义的模块标识的数组字面量。

3) factory:一个需要进行实例化的函数或一个对象,无依赖模块可以直接使用对象字面量来定义。

RequireJS 是一个前端的模块化管理的工具库,遵循AMD规范。

RequireJS 的基本思想为:通过一个函数来将所有所需要的或者说所依赖的模块实现装载进来,然后返回一个新的函数(模块),所有的关于新模块的业务代码都在这个函数内部操作,其内部也可无限制的使用已经加载进来的模块。

defined用于定义模块,RequireJS要求每个模块均放在独立的文件之中。按照是否有依赖其他模块的情况分为独立模块和非独立模块。

1) 独立模块,不依赖其他模块,直接定义:

define({
	method1: function() {},
	method2: function() {}
});

等价于

define(function() {
	return {
 		method1: function() {},
 		method2: function() {}
	}
});

2) 非独立模块,对其他模块有依赖:

define(['module1', 'module2'], function(m1, m2) {
	...
});

等价于

define(function(require) {
	var m1 = require('module1'),
	var m2 = require('module2');
	...
});


4、CMD与SeaJS:

在CMD中,一个模块就是一个文件,格式为:define( factory );

全局函数define,用来定义模块。

参数 factory可以是一个函数,也可以为对象或者字符串,当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。

1)  定义JSON数据模块:

define({ "foo": "bar" });

2) 通过字符串定义模板模块:

define('this is {{data}}.');

3) factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口:

define(function(require, exports, module) { 
    ...
});

语法:define([id], [deps], factory);

字符串id为模块标识(可选),数组deps为模块依赖(可选),factory有三个参数,一是require, 二是export,三是modules。

1) require

① require( id ):接受模块标识作为唯一的参数,用来获取其他模块提供的接口。

define(function(require, exports) {
	var a = require('./a');
	a.funA();
});

② require.async( id, [callback]):require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载。

define(function(require, exports, module) { 
	require.async('.a', function(a) {
		a.funA();
	});
});

③ require.resolve( id ):可以使用模块内部的路径机制来返回模块路径,不会加载模块。

2) export

export用来向外提供模块接口。

define(function(require, exports) {
    exports.foo = 'bar'; // 向外提供的属性
    exports.do = function(){}; // 向外提供的方法
});

当然也可以使用 return 直接向外提供接口。

define(function(require, exports) {
    return{
        foo : 'bar', // 向外提供的属性
        do : function(){} // 向外提供的方法
    }
});

也可以简化为直接对象字面量的形式。

define({
    foo : 'bar', // 向外提供的属性
    do : function(){} // 向外提供的方法
});

3) module

module为一个对象,存储了一些与当前模块相关联的属性与方法:

① module.id 为模块的唯一标识。

② module.uri 根据模块系统的路径解析规则得到模块的绝对路径。

③ module.dependencies 表示模块的依赖。

④ module.exports 当前模块对外提供的接口。

SeaJS:

核心特征:

1) 遵循CMD规范,与NodeJS般的书写模块代码。

2) 依赖自动加载,配置清晰简洁。

seajs.use :用来在页面中加载一个或者多个模块。

// 加载一个模块 
seajs.use('./a');
// 加载模块,加载完成时执行回调
seajs.use('./a', function(a) {
    a.funA();
});
// 加载多个模块执行回调
seajs.use(['./a','./b'], function(a , b) {
    a.funA();
    b.funB();
});

其define 与 require 使用方式基本就是CMD规范中的示例。

 

5、AMD与CMD的区别

1) 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。但RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。

2) AMD 推崇依赖前置;CMD 推崇依赖就近。

AMD:

define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
	a.funA();
	...
	b.funB();
	...
})

CMD:

define(function(require, exports, module) {
	// 依赖可以就近书写
	var a = require('./a');
	a.funA();
	...
	var b = require('./b')
	b.funB();
	... 
})
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值