理解AMD ,CMD,CommonJS规范

https://blog.csdn.net/xcymorningsun/article/details/52709608

 

理解AMD ,CMD,CommonJS规范

这是一篇关于javascript模块化AMD,CMD,CommonJS的学习总结,做为记录也给一样对三种方式有疑问的童鞋们,有不对或者误差之处,望各位大神指出,不胜感激。javascript

本篇默认读者大概知道require,seajs的用法(AMD,CMD用法),因此没有加入使用语法。html

 

 

一、为什么而生:java

 这三个规范都是为javascript模块化加载而生的,都是在用到或者预计要用到某些模块时候加载该模块,使得大量的系统巨大的庞杂的代码得以很好的组织和管理。模块化使得咱们在使用和管理代码的时候不那么混乱,并且也方便了多人的合做。jquery

 

二、那些规范们:git

      (1)、CommonJS 是一个有志于构建 JavaScript 生态圈的组织。整个社区致力于提升 JavaScript 程序的可移植性和可交换性,不管是在服务端仍是浏览器端。es6

     a groupwith a goal of building up the JavaScript ecosystem for web servers, desktopand command line apps and in the browser.github

    一个有目标的构建JavaScript生态系统Web服务器组,在浏览器和命令行应用程序和桌面。(他本身wiki上这么说的)web

           这个组织呢制定了一些规范 (能够去他们网站看看 http://www.commonjs.org/)包括CommonJS Modules/1.0 规范,咱们平时所说的commonjs规范,说的就是这个了。api

          “TheCommonJS API will fill that gap by defining APIs that handle many commonapplication needs, ultimately providing a standard library as rich as those ofPython, Ruby and Java. ”--(出自 http://www.commonjs.org/跨域

    因此说Commonjs是一个更偏向于服务器端的规范。Node.js采用了这个规范。 根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读 取一个文件并执行,最后返回文件内部的exports对象。

       他又说了,能够用在下面这些场景  ,因此他更明显的偏向服务器端。固然你也能够把它用在浏览器里边(他们本身说能够)。

·       Server-side JavaScript applications

·       Command line tools

·       Desktop GUI-based applications

·       Hybrid applications (Titanium, Adobe AIR)

  

  (2)、AMD规范

    Commonjs解决了模块化的问题,而且能够用在浏览器中,可是Commonjs是同步加载模块,当要用到该模块了,现加载现用,这种同步机制到了浏览器里边就有问题了,加载速度啊啥的(览器同步加载模块会致使性能、可用性、调试和跨域访问等问题)。

    鉴于浏览器的特殊状况,又出现了一个规范,这个规范呢能够实现异步加载依赖模块,而且会提早加载那就是AMD规范。AMD能够做为CommonJS模块一个中转的版本只要CommonJS没有被用来同步的require调用。使用同步require调用的CommonJS代码能够被转换为使用回调风格的AMD模块加载器(https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88) (它说的)。

    

    下面是一个使用了简单CommonJS转换的模块定义(它是amd规范的一种用法):

     define(function (require, exports, module) {

       var a = require('a'),

           b = require('b');

 

       exports.action = function () {};

     });

    因此说AMD和Commonjs是兼容的,只要稍稍调换一下调用方法就实现了同步加载(我很怀疑amd也是在commonjs基础上加了个壳,而后并无找到其余的神马说明和支持的文字,找到了必定加到这)。

    看一下AMD规范你会发现,AMD基本都是提早说明依赖模块,而后预加载这些模块,实际上这就要求你提早想好这些依赖,提早写好,否则写代码过程当中要回到开头继续添加依赖。

 

  (3)、CMD

    不知道是否是针对这个问题,淘宝的玉伯大牛搞了个seajs出来,并声称这个规范是遵循CMD规范的,而后给出了这个规范的一个链接(打开会发现draft字样)。关于这个规范呢玉伯在知乎是这么说的

      ”AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出。

      CMD 是 SeaJS 在推广过程当中对模块定义的规范化产出。
      相似的还有 CommonJSModules/2.0 规范,是 BravoJS 在推广过程当中对模块定义的规范化产出。
      还有很多⋯⋯

      “

     因此这个规范其实是为了Seajs的推广而后搞出来的。那么看看SeaJS是怎么回事儿吧,基本就是知道这个规范了。

    一样Seajs也是预加载依赖js跟AMD的规范在预加载这一点上是相同的,明显不一样的地方是调用,和声明依赖的地方。AMD和CMD都是用difine和require,可是CMD标准倾向于在使用过程当中提出依赖,就是无论代码写到哪忽然发现须要依赖另外一个模块,那就在当前代码用require引入就能够了,规范会帮你搞定预加载,你随便写就能够了。可是AMD标准让你必须提早在头部依赖参数部分写好(没有写好? 倒回去写好咯)。这就是最明显的区别。

 

三、共生共处

  因为CommonJS是服务器端的规范,更另外两个标准实际不冲突。

  AMD在国外用的更多,固然国内也是很多的,jQuery1,7版本开始使用,Dojo在1.6版本开始用,这已经可以证实它足够牛x了。

  CMD固然也有不少人在用,可是基本都集中在国内,Seajs官网就展现了一大堆牛逼的公司在用(包括爱奇艺,腾讯微博,支付宝,淘宝等一大堆,去这看看http://seajs.org/docs/),估计小的不出名的也不可胜数了,毕竟不少公司招聘都要求会seajs嘛。

      因此三个规范目前都挺好(其实也主要是由于js么有本身的模块加载机制,es6出来以后不知道会怎样)。

  当咱们写一个文件须要兼容不一样的加载规范的时候怎么办呢,看看下面的代码。

  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

(function (root, factory) {

 

    if (typeof define === 'function' && define.amd) {

 

        // AMD

 

        define(['jquery', 'underscore'], factory);

 

    } else if (typeof exports === 'object') {

 

        // Node, CommonJS之类的

 

        module.exports = factory(require('jquery'), require('underscore'));

 

    } else {

 

        // 浏览器全局变量(root 即 window)

 

        root.returnExports = factory(root.jQuery, root._);

 

    }

 

}(this, function ($, _) {

 

    // 方法

 

    function a(){}; // 私有方法,由于它没被返回 (见下面)

 

    function b(){}; // 公共方法,由于被返回了

 

    function c(){}; // 公共方法,由于被返回了

 

      

 

    // 暴露公共方法

 

    return {

 

        b: b,

 

        c: c

 

    }

 

}));   

这个代码能够兼容各类加载规范了。

  

四、AMD和CMD的区别

     下面这几点是玉伯在知乎上说的。

 

  1. 对于依赖的模块,AMD 是提早执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改为能够延迟执行(根据写法不一样,处理方式不一样)。CMD 推崇 as lazy aspossible.

  2. CMD 推崇依赖就近,AMD 推崇依赖前置。

 

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

 

  4. 还有一些细节差别,具体看这个规范的定义就好,就很少说了。

     ( 好吧~第四点是很少说了。。。。。。。。。)

 

五、AMD和CMD的一些相同

  都有difine和require,并且调用方式实际均可以添加依赖参数,也就是说均可以用提供依赖参数的方式来实现预加载依赖模块(可是不推荐由于  注意:带 id 和 deps 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。---来自:https://github.com/seajs/seajs/issues/242)。

     AMD也能够在factory中使用require来现加载用到的模块,可是这个模块就不会预先加载,属于用到才加载的同步加载了。

    var a = require('a'); //加载模块a

相关文章
相关标签/搜索