前端模块化(二):模块化编程

所谓的模块化编程就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是相互独立,实现某一特定的功能。如果其他模块想调用的时候,可以暴露我们所希望对外的公开的方法与数据。

1、函数写法

function f1(){ 
        var value=1; 
    //...  
}  

function f2(){
        var value=2;   
    //...  
}  

这里定义了f1跟f2,每个函数相当于一个模块,f1跟f2是相互独立的,不能访问到对方里面的局部内容value;这种写法定义了全局变量f1、f2污染了全局环境会导致命名冲突(在上一篇文章提过)。

 

2、对象写法

var myModule= new Object({
    value : 0,
    f1 : function (){
      //...
    },

    f2 : function (){
      //...
    }
});

把函数f1()和f2(),封装在myModule对象里。使用的时候,就是调用这个对象的属性即可:myModule.f1()。这样的写法会暴露所有模块成员,内部状态可以被外部改写如:myModule.value=1 ,会改变myModule内部的属性值。同时这种办法只能一定程度上减少了命名冲突的问题,不能完全避免命名冲突。

 

3、立即执行函数写法

(1)匿名闭包写法 

(function () { 
    // ... 
}()); 

javascript中没用私有作用域的概念,根据javascript函数作用域链的特性,使用这种写法可以模仿一个私有作用域。在闭包中,可以定义私有变量和函数,外部无法访问它们,从而做到了私有成员的隐藏和隔离,俗称“匿名包裹器”或“命名空间”。

(2)全局引入写法

(function (a) { 
     a.a3 = function () {
      //...
   };
    //
}(a)); 

将a对象作为参数传入,在函数体内对这个对象进行操作。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。现在很多类库里都有这种使用方式,比如jQuery源码

(3)模块导出写法

var myModule = (function(){
    
var value = 0;     var f1 = function(){       //...     };     var f2 = function(){       //...     };     return { value: value,       f2 : f2     }; })();

这里,我们声明了一个全局的模块叫myModule,它包含二个属性,一个成员变量value和一个成员方法f1。除此之外,它还使用匿名函数的闭包维护了私有内部状态,我们也可以通过按需传入外部变量。

(3)扩展模式写法

var myModule = (function (a) { 

       var value =a.value;
    var f1 = function(){
      //...
    };

    var f2 = function(){
      //...
    };

    return {
          value: value,
      f2 : f2
    };

}(a));

这里,我们在闭包中定义私有变量和函数,外部无法访问它们,做到了私有成员的隐藏和隔离。将某对象作为参数传入,在函数体内对该对象进行操作,然后返回对象或函数。由此,可以做到把依赖项通过参数的形式注入进来在内部使用注入的属性,并且可以暴露我们所希望对外的公开的方法与数据。这就是模块化编程的基础思想。

在此思想之下,javaScript模块化编程开始盛行,大牛们开始进行各式各样的封装打包,从而产出一系列的模块化规范、模块化加载器。上面的方法中,a必须在模块myModule之前定义,如果a依赖项自身是一个大的模块,比如一个库,我们如何做到在myModule之前定义加载a,然后在myModule中成功地引用a呢?模块化加载器便能帮我们解决这个问题。

下一篇我们开始介绍模块化规范的先驱-------CommonJS规范;

 

posted @ 2017-12-03 20:39  灰锅  阅读(706)  评论(0编辑  收藏  举报