javascript 模块化

本文介绍了JavaScript模块化的演变过程,从原始写法到使用立即执行函数隐藏私有成员,再到引入CommonJS、AMD和CMD规范。重点讲解了AMD规范及其在require.js中的应用,包括模块的加载方式、自定义加载行为及非AMD规范库的加载方法。

1.模块的写法

  a、原始写法:

function m1() {..........}

function m2() {..........}

    这两个函数组成一个模块,使用时直接调用,但是这样明显污染全局环境,无法保证不与其他的模块发生变量名冲突,并且这样也看不出来各个模块之间的依赖关系。

  b、后来写成对象:

var module1 = new Object({
        _count : 0,
        m1 : function (){
                //...
            },
        m2 : function (){
               //...
            }
});                        

    这样就写module.m1(); 但是这样暴露了所有模块成员,内部代码可以被外部改写。比如外部代码可以直接改变内部计数的值  :module1._count =5;

  c、使用立即执行函数可以达到不暴露私有成员变量的目的。

var module1 = (function(){
    var _count = 0;
    var m1 = function(){
      //...
    };
    var m2 = function(){
      //...
    };
    return {
      m1 : m1,
      m2 : m2
    };
})();

  d、后来又有了宽放大的模式

var module1 = ( function (mod){
    //...
    return mod;
})(window.module1 || {});

 

2.出现模块化规范,目前有 :CommonJS模块、AMD模块还有CMD模块 几种规范。

  a、CommonJS规范同步加载模块,这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。
 

var math = require('math');
math.add(2, 3)

 

  b、主要讲AMD异步加载模块加载采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
AMD也采用require加载模块 require([module], callback);第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数
 

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

  math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。require.js这个JavaScript的库实现了AMD规范

 

3.require.js用法

  a、开始引用js文件

<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>

  这样的方式加载有两个缺点:加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长(解决方法在下边);其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序

  b、require.js解决了这个问题 <script src="js/require.js" defer async="true" ></script>
async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。加载require.js以后就需要 加载我们自己的代码了,写一个main.js 这就相当于c语言的main()入口;
<script src="js/require.js" data-main="js/main"></script> data-main属性的作用是,指定网页程序的主模块

main.js --------->
  require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // some code here
  });

  require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
  require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

  c、自定义模块的加载行为 :使用require.config()方法进行定义;写在main.js的头部。

require.config({
    paths: {
           // 或者写上baseUrl: "js/lib",下边就不用写lib
      "jquery": "lib/jquery.min",
      "underscore": "lib/underscore.min",
      "backbone": "lib/backbone.min"
    }
  });    

  如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度。因此,require.js提供了一个优化工具,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数。

 

4.加载方式完了,然后就是自己写的模块 应该用AMD规范进行,写模块必须采用特定的define()函数来定义;
    

---------------->// math.js模块
  define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  }); 

 


  b、如果这个模块依赖其他的模块怎么办?

---------------->// math.js模块
  define(['myLib'], function(myLib){
    function foo(){
      myLib.doSomething();
    }
    return {
      foo : foo
    };
  });

 

5.很多的库的模块并不符合AMD规范那么怎么进行加载呢?那加载他们之前必须要先定义他们的特征,比如加载underscore和backbone

require.config({
    shim: {
      'underscore':{
        exports: '_'
      },
      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }
    }
});

  require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。

 

参照文档:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html(阮一峰)  自己理解

 

转载于:https://www.cnblogs.com/pomelo1/p/8622059.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值