zoukankan      html  css  js  c++  java
  • js 模块化的规范

           The Module Pattern,模块模式,也译为模组模式,是一种通用的对代码进行模块化组织与定义的方式。这里所说的模块(Modules),是指实现某特定功能的一组方法和代码。许多现代语言都定义了代码的模块化组织方式,比如 Golang 和 Java,它们都使用 package 与 import 来管理与使用模块,而目前版本的 JavaScript 并未提供一种原生的、语言级别的模块化组织模式,而是将模块化的方法交由开发者来实现。因此,出现了很多种 JavaScript 模块化的实现方式,比如,CommonJS Modules、AMD 等。 

    1、CommonJS 是一个有志于构建 JavaScript 生态圈的组织。整个社区致力于提高 JavaScript 程序的可移植性和可交换性,无论是在服务端还是浏览器端。

         a group with a goal of building up the JavaScript ecosystem for web servers, desktop and command line apps and in the browser.

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

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

              “The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, 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 在推广过程中对模块定义的规范化产出。
          类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。
          还有不少⋯⋯

          “

         所以这个规范实际上是为了Seajs的推广然后搞出来的。那么看看SeaJS是怎么回事儿吧,基本就是知道这个规范了。

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

    简单的区别


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

    区别:

    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 都简单纯粹

     CommonJS 与AMD,CMD的区别

    CommonJS服务器端范畴,AMD,CMD客户浏览器端范畴

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

    (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
     
        }
     
    }));   

    参考文档

    https://my.oschina.net/chenzhiqiang/blog/129783

    扩展阅读:
     
     
    前端模块化开发的价值 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 

     
  • 相关阅读:
    【转】WINDOWS消息响应,以及处理分派机制
    web服务器分析与设计(四)
    c++ 概念及学习/c++ concept&learning(三)
    c++ 概念及学习/c++ concept&learning(二)
    【重读】The C++ Programming Language/C++编程语言(一)
    web服务器分析与设计(三)
    web服务器分析与设计(二)
    web服务器分析与设计(一)
    c++ 概念及学习/c++ concept&learning(一)
    windows服务1053错误排查
  • 原文地址:https://www.cnblogs.com/surfaces/p/5898925.html
Copyright © 2011-2022 走看看