以代码爱好者角度来看AMD与CMD_柯奇士 秋天肺 五行角度来看

以代码爱好者角度来看AMD与CMD_柯奇士 秋天肺 五行角度来看

随着浏览器功能越来越完善,前端已经不仅仅是切图做网站,前端在某些方面已经媲美桌面应用。越来越庞大的前端项目,越来越复杂的代码,前端开发者们对于模块化的需求空前强烈。后来node出现了,跟随node出现的还有commonjs,这是一种js模块化解决方案,像Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式 ,CommonJS加载模块是同步的,所以只有加载完成才能执行后面的操作。但是浏览器环境不同于Node,浏览器中获取一个资源必须要发送http请求,从服务器端获取,采用同步模式必然会阻塞浏览器进程出现假死现象。在这方面dojo曾经做了伟大尝试,早期dojo便是采用xhr+eval的方式,结果可想而知,阻塞现象是必然的。后来出现无阻塞加载脚本方式在开发中广泛应用,在此基础结合commonjs规范,前端模块化迎来了两种方案:AMD、CMD.

借用三藏法师一句话:人是人他妈生的,妖是妖他妈生的。此话虽不雅,但用这里却颇为贴切。AMD 是 RequireJS在推广过程中对模块定义的规范化产出,CMD是SeaJS 在推广过程中对模块定义的规范化产出。一位出自dojo加载器的作者JamesBurke,一位出自国内前端大师玉伯。二者的区别,玉伯在12年 如是说 :

RequireJS 和 SeaJS 都是很不错的模块加载器,两者区别如下:1. 两者定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端2. 两者遵循的标准有差异。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。3. 两者社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,而采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。4. 两者代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。5. 两者对调试等的支持有差异。SeaJS 通过插件,可以实现 Fiddler 中自动映射的功能,还可以实现自动 combo 等功能,非常方便便捷。RequireJS 无这方面的支持。6. 两者的插件机制有差异。RequireJS 采取的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采取的插件机制则与 Node 的方式一致:开放自身,让插件开发者可直接访问或修改,从而非常灵活,可以实现各种类型的插件。.

关于二者的区别,前人之述备矣:

而在本文,我们仅从代码爱好者的角度来一窥二者API、模块管理、加载、执行的异同。

对比AMD与CMD规范,二者最大的区别在于依赖模块的执行时期,CMD规范中明确要求延迟执行(Execution must belazy.)。这一点从二者在模块的定义方法define的函数签名上可以看出:

AMD中define如下定义:

   define(id?, dependencies?, factory);
define(["./a", "./b"], function(a, b) {  //BEGIN  a.doSomething();  b.doSomething();});

CMD中模块如下定义:

define(function(require, exports, module) {  // The module code goes here});

一个模块使用define函数来定义

  1. define函数只接受一个模块工厂作为参数
  2. factory必须是一个函数或者其他有效值
  3. 如果factory是一个函数,如果指定参数的话,前三个必须是“require”,“exports”,“module”
  4. 如果factory不是一个函数,那么模块的exports属性被设置为那个有效对象
define(function(require, exports, module) {  //BEGIN  require("./a").doSomething();  require("./b").doSomething();});

需要提一下的是二者对待依赖模块的加载是一致的,在factory执行时,依赖模块都已被加载。从代码上来看,AMD中在BEGIN处a、b的factory都是执行过的;而CMD中虽然a、b模块在BEGIN已被加载,但尚未执行,需要调用require执行依赖模块。这就是CMD中着重强调的延迟执行。如果这个例子不明显的话,我们来看一下条件依赖:

AMD:

define(["./a", "./b"], function(a, b) {  //BEGIN  if (true) {    a.doSomething();  } else {b.doSomething();  }  //END});

CMD:

define(function(require) {   // BEGIN  i f(some_condition) {    require('./a').doSomething();  } else {    require('./b').soSomething();  }  // END});

条件依赖意思是我们根据条件使用依赖项,在AMD中BEGIN位置处a、b模块都需要被执行一次。CMD中BEGIN处a、b都没有被执行,在END处,a、b只有一个被实际执行过。

那么问题来了,javascript作为脚本语言,代码肯定是顺序执行的,作为AMD与CMD的实现者,requireJs与seaJs是如何知道需要加载的所有文件呢?又是如何做到异步加载?对于seajs,factory中代码肯定是顺序执行的,但是这必须导致require时的阻塞加载,而她又是如何保证异步加载的?

每一个卓越的思想都有一份朴实的代码实现。所以无论AMD与CMD都要面临以下几个问题:

1、模块式如何注册的,define函数都做了什么?

2、他们是如何知道模块的依赖?

3、如何做到异步加载?尤其是seajs如何做到异步加载延迟执行的?

辩证法第一规律:事物之间具有有机联系。AMD与CMD都借鉴了CommonJs,宏观层面必有一致性,比如整体处理流程:

模块的加载解析到执行过程一共经历了6个步骤:

1、由入口进入程序

2、进入程序后首先要做的就是建立一个模块仓库(这是防止重复加载模块的关键),JavaScript原生的object对象最为适合,key代表模块Id,value代表各个模块,处理主模块

3、向模块仓库注册一模块,一个模块最少包含四个属性:id(唯一标识符)、deps(依赖项的id数组)、factory(模块自身代码)、status(模块的状态:未加载、已加载未执行、已执行等),放到代码中当然还是object最合适

4、模块即是JavaScript文件,使用无阻塞方式(动态创建script标签)加载模块

scriptElement= document.createElement_x('script');scriptElement.src = moduleUrl;scriptElement.async = true;scriptElement.onload = function(){.........};document.head.appendChild(scriptElement);

5、模块加载完毕后,获取依赖项(amd、cmd区别),改变模块status,由statuschange后,检测所有模块的依赖项。

由于requirejs与seajs遵循规范不同,requirejs在define函数中可以很容易获得当前模块依赖项。而seajs中不需要依赖声明,所以必须做一些特殊处理才能否获得依赖项。方法将factory作toString处理,然后用正则匹配出其中的依赖项,比如出现require(./a),则检测到需要依赖a模块。

同时满足非阻塞和顺序执行就需要需要对代码进行一些预处理,这是由于CMD规范和浏览器环境特点所决定的。

6、如果模块的依赖项完全加载完毕(amd中需要执行完毕,cmd中只需要文件加载完毕,注意这时候的factory尚未执行,当使用require请求该模块时,factory才会执行,所以在性能上seajs逊于requirejs),执行主模块的factory函数;否则进入步骤3.

最后,无论requireJs还是seaJs都已被广泛应用于web开发中,实际选取时应根据以下几方面综合平衡选取:

1、功能能否满足项目需求

2、文档、demo的详尽程度

3、框架的学习曲线

4、社区的活跃度

如果您觉得这篇文章对您有帮助,请不吝点击推荐。

--
http://www.lexue163.com/v_361_dIwE5JLfNP54.html

  

爱华网本文地址 » http://www.413yy.cn/a/25101015/250355.html

更多阅读

AMD与Intel的CPU处理器到底哪个好 芝奇和金士顿哪个好

  AMD与Intel的CPU处理器到底哪个好?用户在打算组装电脑的时候,开始常常会比较纠结,AMD处理器与Intel处理器到底哪个好?一般我们都清楚Intel处理器以高端为主,品质肯定没问题,价格也比较贵,而AMD价格便宜很多,性价比高,两者之间如何选择,用

苏、黄的书法与诗法 苏士澍书法价格

内容提要 苏轼、黄庭坚倡导的“尚意”书法,追求“出新意”和“生新奇”,其笔意的纵横曲折与“以文为诗”而重气格的宋诗章法相通。他们的书体,或端庄杂流丽、刚健含婀娜,或雄健奇崛、丰筋多骨,一如其诗体而风格独特,具有“一笔书”的气韵,

以恬淡平静的心态去与人相处 平静心态的句子

素材来源/网络 编辑制作/荷花小女子一、以恬淡平静的心态去与人相处别太刻意让他人感觉到自己的存在,以平静恬淡的心态去做人和处世,才能让他人铭记于心底。他是一个当红的歌星。那天,他的汽车坏了,他把车开到一家维修站,一个年轻的女修

阿帕奇与武直-10对比 武直10与阿帕奇

阿帕奇与武直-10对比个人观点,允许评论阿帕奇与武直-10都是武装攻击直升机,其内部机密相信美国佬和中国军工都不会对外公开,尽管美国佬号称最有军事透明度。美国佬号召别人透明,而把自己悟得严严实实的。这一点就连美国佬自己用实际行动

朱丹前男友宋柯喜得千金微博自曝女儿照片(图) 朱丹与宋柯

朱丹前男友宋柯喜得千金微博自曝女儿照片(图)作者:三峡在线昨天,三峡在线得知消息:太合麦田老总宋柯在本月13日迎来了自己的女儿。女儿名叫宋思文,至于宋思文的妈妈,并不是之前与宋柯传出绯闻的主持人朱丹,而是一位圈外人。事实上,宋柯

声明:《以代码爱好者角度来看AMD与CMD_柯奇士 秋天肺 五行角度来看》为网友咱會狠幸福分享!如侵犯到您的合法权益请联系我们删除