`

AMD规范与CMD规范的区别是什么?

阅读更多

在比较之前,我们得先来了解下什么是AMD规范?什么是CMD规范?当然先申明一下,我个人也是总结下而已,也是网上看到的资料,自己总结下或者可以说整理下而已,供大家更深入的了解!因为我们都知道 AMD规范:是 RequireJS 在推广过程中对模块定义的规范化产出的,而CMD规范:是SeaJS 在推广过程中对模块定义的规范化产出的。

什么是CMD规范?

  在CMD中 一个模块就是一个文件,如下代码所示:

//基本格式如:define(id, deps, factory)
// 比如如下代码
define('hello',['jQuery'],function(require, exports, module) {
  // 模块代码
});
define是一个全局函数,主要是用来定于模块的。其中如上'hello'就是模块名称,['jquery']是依赖项,也可以依赖于多项可以如下写法['jquery','',''],分别用逗号隔开,其中上面的id(模块名称)和deps(被依赖项) 是可以省略的。省略时,那么模块名称就是文件名称。比如我有个文件叫a.js,那么我定义模块时候如下代码所示:
define(function(require, exports, module) {
  // 模块代码
});
那么如果我想在b.js代码里面要依赖于a.js的话,那么我可以直接这样写:
define(function(require,exports,module){ var a = require('a')});
但是注意:带有id 和 deps 是不属于CMD规范的。所以在seaJS里面 一般的写法是不带模块名称和依赖项的。就是如上的代码格式。
下面看看 factory  在seajs里面 factory既可以是函数,对象或者字符串。factory为对象 字符串时候,表示该模块的接口就是该对象或者字符串,如下可以定义一个json对象。
define({"aa":'bb'});和jsonp格式类似,不过这样的数据对象是高度可用的,而且因为是静态对象,他也是CDN友好的,可以提高性能,比如说我们 有个省市区这么一个jSON格式要返回我们前端,如果以传统JSONP的形式提供给客户端,它必须提供一个callback函数名,根据这个函数名动态生成返回数据,这使得标准JSONP数据一定不是CDN友好的。那么我们可以利用这种格式
define({  
    provinces: [
    {
        name: '上海', 
        areas: ['浦东新区', '徐汇区']},
    {
        name: '江苏', 
        cities: ['南京', '南通']}
        //.....  
    ]
});
假设这个文件名为china.js,那么如果某个模块需要这个数据,只需要:
define(function(require,exports,module){
     var china = require('./china');
    //在这里使用中国省市数据
});
当factory为函数时,表示该模块的构造方法,执行该构造方法,可以得到模块向外提供的接口。默认会传入三个参数require,exports,module.那么我们先来看看require参数吧!
require:
 require是一个方法,他可以解决依赖,用于获取其他模块提供的接口,比如下面的a.js代码如下

  define(function(require, exports) {
    exports.a = function(){
    // 很多代码 
    };
  });

   那么现在我想在b.js里面调用a.js里面的a方法。我们可以如下做:

   define(function(require,exports){

        var fun = require('./a');

    console.log(fun.a()); // 就可以调用到及执行a函数了。

   })

  require.async(id,callback) :   require.async: 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback参数可选。比如如下代码:
复制代码
define(function(require, exports, module) {

  // 异步加载一个模块,在加载完成时,执行回调
  require.async('./b', function(b) {
    b.doSomething();
  });

  // 异步加载多个模块,在加载完成时,执行回调
  require.async(['./c', './d'], function(c, d) {
    c.doSomething();
    d.doSomething();
  });

});
复制代码

注意: require是同步往下执行的,而require.async 则是异步回调执行。

 require.resolve(id)

使用模块系统内部的路径解析机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的绝对路径。
复制代码
define(function(require, exports) {

  console.log(require.resolve('./b'));
  // ==> http://example.com/path/to/b.js

});
复制代码

exports

 exports:是一个对象,用来向外提供模块接口。
 比如还是上面的代码:如下a.js里面
define(function(require, exports) {
    exports.a = function(){
        // 很多代码    
    };
});

 或者如下书写:

复制代码
define(function(require, exports) {
    return {
              i: 'a',
              a: function(){ 
                   // 执行相应的代码
              }
        }
});
复制代码

那么如果我在b.js里面想要调用a.js里面的a方法,由于a.js使用exports对外提供了接口a方法,那么在b.js里面 我们只需要先这样 var fun = require('./a');然后执行fun.a();就可以执行a方法了。

module

module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。其中exports是module.exports的一个引用。
moudle.id
 模块的唯一标识。如下代码:
define('id', [], function(require, exports, module) {
  // 模块代码
});
module.uri
根据模块系统的路径解析规则得到的模块绝对路径。
define(function(require, exports, module) {
  console.log(module.uri); 
  // ==> http://example.com/path/to/this/file.js
});
等等属性 具体可以看seajs官网。原理是一样的 因为seajs也采用的是CMD规范。

  什么是AMD规范?

如下官网代码:
复制代码
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
    exports.verb = function() {
        return beta.verb();
        //或者:
        return require("beta").verb();
    }
});
复制代码

  这里的require函数让你能够随时去依赖一个模块,即取得模块的引用,从而即使模块没有作为参数定义,也能够被使用;exports是定义的 alpha 模块的实体,在其上定义的任何属性和方法也就是alpha模块的属性和方法。通过exports.verb = ...就是为alpha模块定义了一个verb方法。例子中是简单调用了模块beta的verb方法。

其中上面的模块名称和依赖项 也可以省略,那么如果省略的话,那么我们可以称他们为匿名函数,那么同样 模块名称就是文件名称 和上面的CMD规范类似。上面的['',''] 参数代表了一组对所定义的模块来说必须的依赖项。第三个参数('definition function')是一个用来为你的模块执行初始化的函数。一个最简单的模块可以以如下方式定义:
复制代码
// 模块定义函数 
// 依赖项(foo 和 bar)被映射为函数的参数
define('myMoudle',['foo','bar'],function(foo,bar){
    // 返回一个定义了模块导出接口的值
    // (也就是我们想要导出后进行调用的功能)
    // 在这里创建模块
    var myModule = {
        doStuff:function(){
            console.log('Yay! Stuff');
        }
    }
    return myModule;
});
复制代码

还可以这样书写:

复制代码
// 另一个例子可以是...
define('myModule',['math', 'graph'], function ( math, graph ) {

        // 请注意这是一个和 AMD 有些许不同的模式,但用几种不同的方式
        // 来定义模块也是可以的,因为语法在某些方面还是比较灵活的
        return {
            plot: function(x, y){
                return graph.drawPie(math.randomGrid(x,y));
            }
        }
    };
});
复制代码

另一方面,require 则主要用来在顶层 JavaScript 文件中或须要动态读取依赖时加载代码。用法的一个实例如下:

复制代码
// 假设 'foo' 和 'bar' 是两个外部模块
// 在本例中,这两个模块被加载后的 'exports' 被当做两个参数传递到了回调函数中
// 所以可以像这样来访问他们
require(['foo', 'bar'], function ( foo, bar ) {
        // 这里写其余的代码
        foo.doSomething();
});
复制代码

动态加载的依赖项 如下代码:

复制代码
define(function ( require ) {
    var isReady = false, 
        foobar;
 
    // 请注意在模块定义内部内联的 require 语句
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });
 
    // 我们仍可以返回一个模块
    return {
        isReady: isReady,
        foobar: foobar
    };
});
复制代码

 CMD规范与AMD规范的区别如下:

 1. CMD依赖就近:比如如下代码

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

   代码在运行时,首先是不知道依赖的,需要遍历所有的require关键字,找出后面的依赖。具体做法是将function toString后,用正则匹配出require关键字后面的依赖。

   而AMD依赖前置:如下代码:

复制代码
define(['./a','./b'],function(a,b){  
       //......  
       a.doSomthing();  
       //......  
       b.doSomthing();  
})  
复制代码

代码在一旦运行到此处,能立即知晓依赖。而无需遍历整个函数体找到它的依赖,因此性能有所提升,缺点就是开发者必须显式得指明依赖——这会使得开发工作量变大,比如:当依赖项有n个时候 那么写起来比较烦 且容易出错。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。

2. 执行顺序上:

  CMD是延迟执行的,而AMD是提前执行的。

3. api设计角度

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

分享到:
评论

相关推荐

    JavaScript模块规范之AMD规范和CMD规范

    首先,AMD规范由RequireJS提出,其主要特点是异步加载模块。`define`函数是AMD的核心,它接受三个参数:模块标识(可选)、依赖项数组和工厂函数。在AMD中,依赖项会在调用工厂函数之前加载,这意味着开发者必须在...

    JS中的模块规范(CommonJS,AMD,CMD

    - **依赖延迟加载**: 在CMD规范中,只有当真正需要依赖时才会去加载它,这与AMD规范有所不同。 示例: ```javascript // 使用 Sea.js 实现 CMD 规范 define(function(require, exports, module) { var dep1 = ...

    JS中的模块规范(CommonJS,AMD,CMD(少用))

    CMD规范的主要特点包括: - CMD同样使用`define()`函数定义模块。 - 模块可以按需加载,即只加载实际需要的部分。 - 支持模块的动态加载,使得代码更为灵活。 CMD的一个示例: ```javascript define(function...

    AMD之require.js与CMD之sea.js

    首先,我们来探讨AMD规范。AMD的设计理念是异步加载模块,这在处理大型复杂应用时非常有用,因为可以实现按需加载和并行加载,提高页面加载速度。RequireJS是AMD规范的代表,它提供了一种动态加载和依赖管理的方式。...

    浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结.docx

    - **背景**:尽管CommonJS很好地解决了服务器端模块化问题,但在浏览器环境中,由于其同步加载机制会导致性能瓶颈和其他问题,因此诞生了AMD规范。 - **特点**: - 异步加载模块。 - 提前声明依赖项,并在模块加载...

    vue文件经过编译使其满足AMDCMD的模式

    当Vue.js项目需要与AMD或CMD规范配合时,例如在一个已经采用RequireJS或Sea.js的大型项目中,Vue文件需要经过特定的编译过程才能适配这两种模块化系统。这个过程通常涉及预处理器或者构建工具,如Webpack、Rollup或...

    将一些js库改写成符合cmd规范的模块

    本话题将深入探讨如何将现有的JavaScript库改写为符合CMD规范的模块,以便更好地在项目中利用和管理这些库。 CMD规范的核心思想是延迟执行和按需加载。它允许开发者在脚本中使用`define`函数来定义模块,并通过`...

    基于CMD规范的fangfis模块合并gulp插件

    1. **模块合并**:能够根据CMD规范,自动解析并合并多个模块文件为一个单一的文件,减少网络请求,提高页面加载速度。 2. **异步调用支持**:支持异步调用模块合并,这意味着在处理大型项目或者有动态依赖时,可以...

    浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结

    AMD规范采用了异步加载模块的方式,它允许指定模块的依赖关系,并在代码执行前就将这些依赖预先加载好,这样当代码执行到依赖模块时,相关模块已经加载完成,可以立即使用。这种方式非常适合浏览器端编程,因为它...

    浅析AMD CMD CommonJS规范–javascript模块化加载学习心得总结

    Seajs是CMD规范的代表实现,其模块定义与AMD类似,但依赖解析更晚执行: ```javascript seajs.use(['a', 'b'], function(a, b) { a.action(); b.action(); }); ``` CMD与AMD的主要区别在于依赖解析时机,CMD更...

    defineadaptation:把按照AMD规范编写的module自动适配到KISSY and seajs的 module定义规范

    现在js的module规范里面,很大一部分都是遵循AMD规范,但是还有很多一部分在使用seajs的CMD规范,以及阿里系的KISSY的module规范(我们对其简称KMD)。 那么,其实我们可以用遵循AMD规范的module,然后把它适配到能...

    gulp-view-compile:用于将html代码打包成cmd,amd规范可以使用的模块。这样可以跨域使用

    用于将html代码打包成cmd,amd规范可以使用的模块。这样可以跨域使用。 Installation npm install gulp-view-compile Test npm test example var rename = require('gulp-rename'); var viewCompile = require('gulp-...

    前端开源库-gulp-cmd-build

    **Cmd**(Common Module Definition)是 Sea.js 提出的一种模块化规范,类似于 AMD(Asynchronous Module Definition)规范,但更注重代码的自然书写顺序。Cmd 支持动态加载模块,使得模块化开发更加灵活。Gulp-cmd-...

    modularJs_exercise:AMD&CMD&CommonJS练习

    RequireJS是一个实现AMD规范的库,它提供了`define`函数来定义模块,并使用`require`来加载依赖。 2. **CMD(通用模块定义)**: CMD是Sea.js提出的另一种模块化规范,它与AMD类似,也支持异步加载,但更注重同步...

    前端开源库-grunt-cmd-transport-wnd

    2. **模块化处理**:支持CMD规范,使得你的代码可以以模块化的方式组织,便于管理和复用。 3. **压缩合并**:将多个JavaScript文件合并成一个文件,减少HTTP请求,同时进行压缩,降低文件大小,提高页面加载速度。 4...

    前端开源库-cmd-build

    这个项目基于CMD(Common Module Definition)规范,CMD是JavaScript模块化的一种实现,类似于AMD(Asynchronous Module Definition),但更侧重于同步加载。 CMD-build的核心功能在于模块打包和转换,它能够处理...

    前端开源库-grunt-cmd-transport-xd

    CMD是Sea.js 推出的一种模块化解决方案,与AMD(Asynchronous Module Definition)规范并行存在,但更倾向于按需加载,减少对整体性能的影响。 Grunt是广受欢迎的JavaScript任务运行器,它允许开发者自动化一系列...

Global site tag (gtag.js) - Google Analytics