js模块化编程规范

一、     CommonJS规范

      我在前边介绍nodejs的文章中提到过模块这个概念,模块就是实现了一定功能的js文件,比如前边使用的sum.js就可以看做是一个模块。

那么为什么需要模块呢?                        

因为使用模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载对应的模块。但是,编写模块需要我们遵守共同的约定,否则你有你的写法,我有我的写法,就乱套了!

约定?                                                    

既然要遵守相同的约定,那么都有哪些约定呢?就是本次要介绍的CommonJS和AMD和CMD,以及es6里面的import和export

首先,要明白,CommonJS和AMD和CMD是约定,是思想,既然是约定,是思想,它就是虚的,就像java里面的接口,并不是真正的实现,这三种规范都有实现了自己的"产物".我们先来看看CommonJS.

        CommonJS在js的应用领域剑走偏锋,它不相信js只能运行在浏览器中,也不满足js只能运行在浏览器中,因此CommonJS定义了很多普通应用程序(主要指非浏览器的应用)使用的API,并希图提供类似后端语言的功能,以便让开发人员基于CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的宿主环境里。

        功夫不负有心人,是金子总会发光的,大名鼎鼎的nodejs产生了,将javascript语言用于服务器端编程,而NodeJS就是CommonJS规范的实现,webpack 也是以CommonJS的形式来书写。

这里再说一下为什么模块必须要有?            

        在浏览器环境下编写javascript,没有模块其实也不是特别大的问题,因为毕竟网页程序的复杂性有限,不使用模块也能完成;但是在服务器端,不使用模块化编程的思想就很难了,因为凡是涉及到服务端的编程一般都不会太简单。

 

        我们前边说了那么多nodejs,你可能不知道nodejs在哪里应用到了CommonJS规范,但是你一定在nodejs中见过CommonJS的这些规范,这样是不是可以称作“只见其面,不闻其名”了。

        在CommonJS中,CommonJS定义的模块分为:

                require:模块的引用

                exports:模块的定义(导出)  ,用于导出当前模块的方法或变量

                module:模块的标识(也用于模块导出),module对象就代表模块本身。

大家回忆一下,我们是不是在nodejs中都使用过了,对吧,就像一些成语典故,我们常常挂在嘴边,却不知道它的来历,这次知道nodejs中的require、exports、module出自何处了吧,就是出自CommonJS规范。

二、amd规范

       基于commonJS模块化规范的nodeJS问世之后,服务端的模块概念已经形成,接下来大家考虑到的自然就是客户端模块了。那么能不能复制CommonJS规范在服务端的应用,把CommonJS应用于客户端浏览器环境呢?比如

  var math = require('math');

  math.add(2, 3);

        这是符合CommonJS规范的代码,math.add(2, 3)在在第一行require('math')之后运行,因此必须等math.js加载完成才能执行下面的代码。也就是说,CommonJS里面的require 是同步的。这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器可能会处于"假死"状态。

        基于上边的原因,客户端(浏览器)的模块化不能使用同步化的CommonJS,那么就只能采用"异步加载"(asynchronous)了。在这个大形势下,AMD规范就应运而生了。

        AMD是"Asynchronous Module Definition"的缩写,翻译过来就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

       AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

require([module], callback);

参数说明:  

[module]:是一个数组,里面的成员就是要加载的模块。

callback:是加载成功之后的回调函数

把上面的代码改写成AMD形式,就是下面这样:

 require(['math'], function (math) {
    math.add(2, 3);
 });

实现了amd规范的前端框架有require.js和curl.js。 

三、cmd规范

       有个框架叫sea.js,也被称作seajs,就是遵循cmd模块化编程规范开发出来的,作用与requirejs是一样的,都是js文件的加载器。下面是官方对seajs和requirejs的比较:

相同之处

RequireJS 和 Sea.js 都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。

不同之处

两者的主要区别如下:

  1. 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。

  2. 遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。

  3. 推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。

  4. 对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。

  5. 插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。

总之,如果说 RequireJS 是 Prototype 类库的话,则 Sea.js 致力于成为 jQuery 类库。

以前用过一个类似于easyui的前端框架叫做bui,官网是http://www.builive.com,使用风格有一种seajs,大家可以参考下:

image.png

 

如下是相关的js代码:

  <script src="http://g.tbcdn.cn/fi/bui/jquery-1.8.1.min.js"></script>
  <script src="http://g.alicdn.com/bui/seajs/2.3.0/sea.js"></script>
  <script src="http://g.alicdn.com/bui/bui/1.1.21/config.js"></script>
 
<!-- script start --> 
    <script type="text/javascript">
        BUI.use('bui/calendar',function(Calendar){
          var datepicker = new Calendar.DatePicker({
            trigger:'.calendar',
            autoRender : true
          });
        });
    </script>

其实js模块化编程规范写了这么多,大家只需要知道有这么3个规范以及这3个规范的典型实现就可以了。我们在学的是遵循着commonjs规范的nodejs,并没有一定要学会requirejs和seajs才能学会nodejs的说法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值