利剑出鞘直指AMD/CMD/UMD及CommonJS

    刚学会前端核心技能的菜鸟一般都会对AMD和CMD比较懵,为啥还有requireJS和seajs,最后还半路杀出个CommonJS,内心一万匹四不像在奔跑......刚有的成就感,瞬间崩塌。其实有这种赶脚的,个人觉得都是不系统化总结记忆、分析的程序猿们,往这看--AMD( require.js )与CMD( sea.js ),CommonJS一般是服务于nodejs,这样就清晰了咩。下面由一枚游走在前端大坑中的程序猿帮大家系统整理下,欢迎大家互相交流学习~~~   

一、commonJS

    根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在一个文件定义的变量(还包括函数和类),都是私有的,对其他文件是不可见的。

    如果你在Node.js平台上写过东西,你应该会比较熟悉CommonJS规范。与前面的AMD及CMD规范不一样的是,CommonJS规范一般应用于服务端(Node.js平台),而且CommonJS加载模块采用的是同步方式(这跟他适用的场景有关系)。同时,得力于Browserify这样的第三方工具,我们可以在浏览器端使用采用CommonJS规范的js文件。

    下面是使用CommonJS规范声明一个名为foo模块的方式,同时依赖jquery模块,

        //  filename: foo.js

        //  dependencies 

              var $ = require('jquery');

        //  methods 

            function myFunc() {    };

        //  exposed public method (single)

        module.exports = myFunc;

    稍微复杂一点的示例如下,拥有多个依赖以及抛出多个接口,

        // filename: foo.js 

            var $ = require('jquery');  

            var _ = require('underscore');

        // methods 

            function a(){    };    

        // private because it's omitted from module.exports (see below)

            function b() {     };    

        // public because it's defined in module.exports 

            function c(){    };    

        // public because it's defined in module.exports

        // exposed public methods

        module.exports = { b: b, c: c};

二、AMD规范

       AMD规范,全称”Asynchronous Module Definition”,称为异步模块加载规范。一般应用在浏览器端。流行的浏览器端异步加载库RequireJS(中文网站)实现的就是AMD规范。

    AMD讲究的是前置执行。

    // filename: foo.js

        define(['jquery', 'underscore'], function ($, _) {

            // methods

            function a(){    };    // private because it's not returned (see below)

            function b(){    };    // public because it's returned

            function c(){    };    // public because it's returned

            // exposed public methods

            return {b: b, c: c};

        });

    define是AMD规范用来声明模块的接口,示例中的第一个参数是一个数组,表示当前模块的依赖。第二个参数是一个回调函数,表示此模块的执行体。只有当依赖数组中的所有依赖模块都是可用的时,AMD模块加载器(比如RequireJS)才会去执行回调函数并返回此模块的暴露接口。

    注意,回调函数中参数的顺序与依赖数组中的依赖顺序一致。(即:jquery->$,underscore->_)

    当然,在这里我可以将回调函数的参数名称改成任何我们想用的可用变量名,这并不会对模块的声明造成任何影响。

    除此之外,你不能在模块声明的外部使用$或者_,因为他们只在模块的回调函数体中才有定义。

三、CMD规范

    CMD规范,全称”Common Module Definition”,称为通用模块加载规范。一般也是用在浏览器端。浏览器端异步加载库Sea.js实现的就是CMD规范。

    下面是使用AMD规范定义一个名为foo模块的方式,此模块依赖jquery,

    define(function (require, exports, module) {

        // load dependence

        var $ = require('jquery');

        //    methods

        function myFunc() {    };

        //    exposed public methods

        return myFunc;})

      CMD规范倾向依赖就近,稍微复杂一点例子。

        define(function (requie, exports, module) {

            // 依赖可以就近书写

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

            a.test();

            // ...

            // 软依赖

            if (status) {

                var b = requie('./b');

                b.test();

            }

        });

四、UMD规范

    因为AMD,CommonJS规范是两种不一致的规范,虽然他们应用的场景也不太一致,但是人们仍然是期望有一种统一的规范来支持这两种规范。于是,UMD(Universal Module Definition,称之为通用模块规范)规范诞生了。

    客观来说,这个UMD规范看起来的确没有AMD和CommonJS规范简约。但是它支持AMD和CommonJS规范,同时还支持古老的全局模块模式。

    我们来看个示例,

    (function (root, factory) {

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

            // AMD

            define(['jquery'], factory);

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

            // Node, CommonJS-like

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

         } else {

            // Browser globals (root is window)

            root.returnExports = factory(root.jQuery);

          }

        }(this, function ($) {

            function myFunc(){    };

            return myFunc;

         })

      );

    个人觉得UMD规范更像一个语法糖。应用UMD规范的js文件其实就是一个立即执行函数。函数有两个参数,第一个参数是当前运行时环境,第二个参数是模块的定义体。在执行UMD规范时,会优先判断是当前环境是否支持AMD环境,然后再检验是否支持CommonJS环境,否则认为当前环境为浏览器环境(window)。当然具体的判断顺序其实是可以调换的。

    下面是一个更加复杂的示例,

    (function (root, factory) {

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

            // AMD

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

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

            // Node, CommonJS-like

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

          } else {

            // Browser globals (root is window)

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

        }

      }(this, function ($, _) {

            //    methods

            function a(){    };    //    private because it's not returned (see below)

            function b(){    };    //    public because it's returned

            function c(){    };    //    public because it's returned

            //    exposed public methods

            return { b: b, c: c}

        })

    );

 

     同步简书地址:https://www.jianshu.com/p/ae666192b628

     同步博客园地址:https://www.cnblogs.com/MaxQD/articles/10514731.html

你可能感兴趣的:(前端)