paul_cheung

导航

Modular JavaScript[AMD and CommonJS]入门

原文链接:http://addyosmani.com/writing-modular-js/

Modularity

当说到一个应用是模块化的,意思是说它是由一系列耦合度很低、有明确功能的模块所组成。松耦合通过尽可能移除依赖(by removing dependencies)使Apps维护起来更方便;

这里介绍三种书写模块化javascript的方法:AMD, CommonJS, Harmony(proposals for the next version of javascript);

序:实现模块化的基本方法就是使用script loaders(推荐RequireJScurl.js)。从产品发布的角度来看,使用优化工具(如RequireJS optimizer)将scripts连接到一块是不错的选择。页面加载后的动态脚本加载也可能会有用,RequireJS也支持。


AMD(a format for writing modular javascript in the browser)

AMD format的主要目就是为developer提供javascript模块化变成的方案;跟CommonJS的主要区别是:AMD是为browser端而设计;CommonJS面向的是server端;

AMD和CommonJS的简单区别(可能不完全):

  1)scoping:browser中无法对js代码进行完全隔离,只能在function中定义变量使其不会在global中出现,这样很容易导致错误出现: var a=b=0;

    AMD不能很好的解决这个问题。相反,AMD支持将external resource引入local function scope,进而实现local scoping;

    CJS是干净的server端环境,如node,没有global scope;

  2)Distance:对浏览器来说,很多资源都是remote的,虽然资源可能被cache到本地,可请求/获得资源总是费时间的;如果要执行的function在另一个文件中,我们就无法知道这个文件是否已经被load进来或者还要花数秒去获得这个文件;如果不知道function是否已经被定义,那么就不能擅自调用它;

    CJS解决这个问题的方法是:假设所有请求的资源都在本地,或者至少可以在毫秒级甚至微秒级时间内请求到;

  3)Asynchrony:上边所说的distance问题造成的直接结果是,需要异步执行task。浏览器在单独线程内执行javascript,如果此线程在等待远程资源,此时啥也不会执行,用户感觉浏览器没反应了。

    解决这个问题的方法是,当资源被准备好了就执行提取初始化操作和请求回调函数操作(callback function);

    Node主要通过事件驱动编程模型来实现异步;

    简单地说,CJS同步提取module resource,因为资源在微秒级的时间内可以到达,不需要异步!


近观AMD和CJS的formats

AMD:

// define() is a necessary wrapper.
define(
    // dependencies are specified in advance.指定依赖模块
['pkgA/modA', 'pkgA/modB', 'pkgZ/modC'], // the module is declared within a definition function. // dependencies are mapped into function parameters. function (modA, modB, modC) { // inside here is the module's code. // the module is exported to the outside world via the // the definition function's returned value. return modC ? modA : modB; } );
CommonJS:
// there is no explicit wrapper, we just write the module's code. // this is not global scope! the scope is limited to this file only. // "free" variables (`require`, `module`, and `exports`) are // declared to help us define our module and fetch resources.   // dependencies are specified as needed var modC = require('pkgZ/modC');   // the module is exported by decorating the `exports` free variable. exports.foo = modC ? require('pkgA/modA') : require('pkgA/modB');

___________________________________________AMD____________________________________________
|AMD通过将module定义在definition function里来处理异步,definition function实际上是一个回调函数。 |
|当所有依赖module都加载完毕且起源都可用后,它才被调用;                         |    
|________________________________________________________________________________________|

___________________________________________CJS____________________________________________
|CJS尽可能快地执行module代码,只有需要的时候才load/execute the module dependencies;       |
|上边的示例中,'pkgA/modA'和'pkgB/modB'只加载执行其中一个;当没必要加载执行所有modules的情况下,CJS |
|比AMD效率高;                                              |      
|________________________________________________________________________________________|

哪个更给力?在浏览器端,我们要么提前提取依赖模块,要么同步提取;AMD有两个plugin,'has.js'和'has!',这俩可以解决大部分此类问题,但不可能解决所有的情况;
至于代码多少,上边的例子中CJS很明显少一些;
答案是:neither!两个都会用到。
1.AMD在browser中使用会有很多好处,究竟有啥好处,这里
2.AMD和CJS会共存很长时间,很长!能做的是:
  1)用CJS写server端执行的module;
  2)用AMD写可以利用其客户端友好功能的module;

one more thing...看原文。
PS:刚接触,原文的有些意思可能没有理解到位,日后再看!

好文Write Modular JavaScript With AMD,CommonJS & ES Harmony: http://addyosmani.com/writing-modular-js/

posted on 2013-08-02 16:52  paul_cheung  阅读(522)  评论(0)    收藏  举报