踏上前端这条道路以来,我一直以为自己就是个娴熟的切图工,每天只需要做着重复的劳动,切图,做网站。然而,技术的发展是日新月异的,切图工早就面临淘汰。随着浏览器功能越来越完善,前端项目越来越大,代码越来越复杂,为了适应这种变化,越来越要求前端开发模块化。

首先介绍一下什么是模块化。模块化是指解决某一个复杂问题,按照一种分类的思维把问题进行系统分解,并处理。譬如将巨大的系统代码,整合优化分割成高内聚低耦合的模块,达到便于管理,维护和开发的目的。

模块化设计,必须实现以下能力:

  1. 定义封装的模块
  2. 定义新模块对其他模块的以来
  3. 对其他模块的引入支持。

介绍其中最主要的两种规范,CMD和AMD。

AMD 与 RequireJS

AMD:Asynchronous Module Definition 异步模块定义 [e'sɪŋkrənəs]

AMD采用require([module],callback);加载模块,require有两个参数,一个是依赖的模块数组,一个是回调函数。目前主要有两个Javascript库实现了AMD规范,require.js和curl.js

require.js主要解决以下两个问题:

(1)实现js文件的异步加载,避免网页失去响应;

(2)管理模块之间的依赖性,便于代码的编写和维护。

require.js使用方法

(1)下载js加载入页面

(2)加载自己的代码    <script src="js/require.js" data-main="js/main"></script>

main.js 

1 require(['moduleA','moduleB'],function(moduleA,moduleB){
//code here
});
//假定主模块依赖jquery、underscore和backbone这三个模块,main.js就可以这样写:
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){ // some code here });

模块的加载

require.config();    config方法可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径,baseUrl为基目录

//main.js
require.config({ baseUrl:"js/lib", paths:{ "jquery":"jquery.min", "underscore":"underscore".min, "backbone":"backbone.min" } })

AMD模块的写法

模块必须采用特定的define()函数来定义,如果一个模块不依赖于其他模块可以直接定义在define()函数中。

假定一个math模块

  //  math.js

    define(function(){

        var add = function(x,y){

            return x+y;

         };

         return {add:add};

    });

  //  加载方法   main.js

    require(['math'],function(math){

         alert(math.add(1,1));

    });

如果这个模块依赖其他模块,define()函数的第一个参数必须是一个数组,指明该模块的依赖性

define(['myLib'],function(myLib){

    function foo(){

        myLib.func();

    }

     return {foo:foo};

});

//当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。

 require方法调用模块

require(['module1','module2'],function(module1,module2){

     module1.func();

     module2.func();

  })

//在加载 foo 与 bar 两个模块之后执行回调函数实现具体过程。

同时还可以在define定义模块内部进行require调用模块

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

加载非规范的模块

在require()加载之前,先用require.config()方法,定义他们的一些特征。

require.config({

      shim:{

             'underscore':{

                     exports:'_'

                     },

              'backbone':{

                       deps:['underscore','jquery'],

                       exports:'Backbone'
} } }); /*require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义
(1)exports值(输出的变量名),表明这个模块外部调用时的名称;
(2)deps数组,表明该模块的依赖性。*/ //比如jQuery插件定义 shim:{ 'jquery.scroll':{ deps:['jquery'], exports:'jQuery.fn.scroll'
} }

CMD 与 seaJS  (转载)

CMD:Common Module Definition   通用模块加载规范

在CMS中一个模块就是一个文件,格式和AMD有些类似,define(factory);define定义模块,参数factory可以是一个函数或者对象,字符串,当factory为对象字符串时,表示模块的接口是该对象。

定义JSON数据模块:

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

通用字符串定义模板模块

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

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

 define( function(require, exports, module) {
// 模块代码
});

define( id?, deps?, factory );

define也可以接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:

    define( 'module', ['module1', 'module2'], function( require, exports, module ){
// 模块代码
});

其与 AMD 规范用法不同。

 require 是 factory 的第一个参数。
  require( id );
  接受模块标识作为唯一的参数,用来获取其他模块提供的接口:
    define(function( require, exports ){
var a = require('./a');
a.doSomething();
});

require.async( id, callback? );

require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载:

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

exports 是 factory 的第二个参数,用来向外提供模块接口。

    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(){} // 向外提供的方法
});

与nodeJS中一样需要注意的是,一下方式是错误的:

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

需要这么做

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

传 入的对象引用可以添加属性,一旦赋值一个新的对象,那么值钱传递进来的对象引用就会失效了。开始之初,exports 是作为 module.exports 的一个引用存在,一切行为只有在这个引用上 factory 才得以正常运行,赋值新的对象后就会断开引用,exports就只是一个新的对象引用,对于factory来说毫无意义,就会出错。

    module 是factory的第三个参数,为一个对象,上面存储了一些与当前模块相关联的属性与方法。
        module.id 为模块的唯一标识。
        module.uri 根据模块系统的路径解析规则得到模块的绝对路径。
        module.dependencies 表示模块的依赖。
        module.exports 当前模块对外提供的接口。

seaJS

    官网 http://seajs.org/docs/
    sea.js 核心特征:
        1. 遵循CMD规范,与NodeJS般的书写模块代码。
        2. 依赖自动加载,配置清晰简洁。
        兼容 Chrome 3+,Firefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。

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

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

AMD 与 CMD 的区别

  下面是玉伯(sea.js创始人)对于 AMD 与 CMD 区别的解释:

    AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
    CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
    类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出还有不少??
    这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。
    目前这些规范的实现都能达成浏览器端模块化开发的目的。
    区别:
    1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
    2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
    // CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
}) // AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
// ...
})
虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。

    3. AMD 的
API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部
require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use
来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。

    4. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。
       
另外,SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277
扩展阅读:
前端模块化开发的价值 https://github.com/seajs/seajs/issues/547
前端模块化开发那点历史 https://github.com/seajs/seajs/issues/588
从 CommonJS 到 Sea.js https://github.com/seajs/seajs/issues/269    

RequireJS和AMD规范  http://javascript.ruanyifeng.com/tool/requirejs.html

知乎  AMD 和 CMD 的区别有哪些? http://www.zhihu.com/question/20351507

CMD和AMD探秘的更多相关文章

  1. CMD和AMD区别的概括

    CMD和AMD区别   AMD CMD 关于依赖的模块 提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)), 延迟执行 关于依赖的位置 依赖前置 ...

  2. CMD和AMD

    CMD是国内玉伯在开发SeaJS的时候提出来的,属于CommonJS的一种规范,此外还有AMD,其对于的框架是RequireJS. 二者的异同之处: 二者都是异步(Asynchronuous Modu ...

  3. CommonJS、CMD和AMD规范分别是什么

    CommonJS.CMD和AMD规范分别是什么 Commonjs是用在服务器端的,同步的,如nodejs amd, cmd是用在浏览器端的,异步的,如requirejs和seajs 其中,amd先提出 ...

  4. CMD和AMD的区别

    CMD和AMD俩者之间的区别 AMD和CMD最大的区别是对依赖模块的执行时机处理不同 CMD和AMD都是CommonJS延伸而来的,CommonJS是随着node的出现而出现的,它是一个规范,用于定义 ...

  5. 转: cmd和amd的区别

    AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMDCMD 规范在这里:https://github.com/seajs/seajs/issues ...

  6. 两句话概括cmd和amd的区别

    === | === | === | ===AMD | 速度快 | 会浪费资源 | 预先加载所有的依赖,直到使用的时候才执行=== | === | === | ===CMD | 只有真正需要才加载依赖 ...

  7. 模块化规范:CMD和AMD的区别

    https://www.zhihu.com/question/20351507/answer/14859415 AMD(异步模块定义) 是 RequireJS 在推广过程中对模块定义的规范化产出.CM ...

  8. CMD与AMD区别

  9. 研究一下javascript的模块规范(CommonJs/AMD/CMD)

    最近写react需要使用nodejs作为开发环境,需要通过npm安装一些第三方的依赖库,因此慢慢感觉到nodejs基础薄弱对我带来了一些不安全感,尤其是javascript模块这一块听到了很多概念,比 ...

随机推荐

  1. 改变了一下blog的主题,很开心

    调整了一下博客的样式,之前一直想改变下,一直不会这次终于摸索出来一点,不过是最简单的,就是在管理里面的设置,可以定制css代码,修改修改,页面就跟着你的想法走了,有时间好好修改下,暂时这个样子,简单大 ...

  2. assert函数

    这个函数在<cassert>里面,通常用来调试程序. eg: int i=1: assert(i==1):/什么也不做 assert(i==2)://程序会异常退出

  3. 关于三星A7屏幕锁已由管理员、加密政策,或证书存储禁用

    解决办法:设定-安全-清除证书-再返回锁定屏幕-把密码锁定-改为滑动.....

  4. Set Font Properties On Mouse Hover Of Push Button And Text Items At Run time In Oracle Forms

    Change the font size and weight of text items and push buttons on mouse hover in Oracle Forms.   An ...

  5. Oracle同义词学习

    oracle的同义词总结   从字面上理解就是别名的意思,和视图的功能类似.就是一种映射关系.   同义词拥有如下好处:   节省大量的数据库空间,对不同用户的操作同一张表没有多少差别;   扩展的数 ...

  6. BerkeleyDB 多索引查询

    由于性能原因,我们打算将关系型数据库转移到内存数据库中:在内存数据库产品的选型中,我们确定的候选对象有Redis和Berkeley DB: Redis查询效率不错,并且支持丰富的数据存储结构,但不支持 ...

  7. MQ使用几个命令

    一.MQ常见基本指令: MQ现在使用的比较常见,但是在测试过程中,使用命令行直接查询,有时候事半功倍. activemq-admin stop activemq-admin list activemq ...

  8. Java 日期往后推迟n天

    在Java中经常会遇到,以指定的日期为基准,计算向后n天<n可以为正.负数,负数为向前移>. 这时需要在Date类的基础上使用Calendar类,处理方法基本如下: import java ...

  9. 十种JAVA排序算法实例

    一.冒泡(Bubble)排序 复制代码 代码如下: void BubbleSortArray() {       for(int i=1;i<n;i++)       {         for ...

  10. Java源码初学_HashMap

    一.概念 HashMap的实例有两个参数影响其性能:初始容量和加载因子.容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量.加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度.当哈希表 ...