日期:2014-05-16  浏览次数:20397 次

js面向对象--理解闭包
由于js语言自身语法的灵活性,使得在js程序中出现了各种各样的代码风格,但也正因为如此,导致了代码的可读性和可维护性大大降低,特别随着项目的不断更新,js代码的不断增多,到后期维护时甚至连自己写的代码都不知所以然了,因此确定一种好的代码风格是很有必要的。

近两年随着ajax的兴起,js变得越来越受“重用”,js开始在web开发中中充当着非常重要的角色,因此也开始遇到了各种各样的问题。于是很多牛人们就提出了js的面向对象编程方法。

使用面向对象的编程思想实现js代码其实也并不难,实现方法也又多种,比如prototype原型,new object()等方法。前面的每个方法都有其自己的优缺点,但都存在一个问题,那就是对于js变量作用域的控制。如果不能很好控制js变量作用域,就可能导致对象内部变量被外部肆意修改,从而导致程序被破坏,不便于程序的维护,对象的封装特性和程序健壮性都大打折扣。被由于js本身没有很好的对变量范围的定义(public/private等限定符),因此在js的面向对象编程中也就遇到了变量的控制问题,特别是对于对象内部的公有变量在prototype原型方法中都很难实现。

如下面一段程序:


function testCls(a){
        this.a=a;
}
testCls.prototype.alertA=function(){
         alert(this.a);
}
var test=new testCls(5);
test.alertA();  //弹出5
alert(test.a);  //同样弹出5



要在其方法alertA中显示对象的内部公用变量a的值就必须在构造函数中通过this赋值,然后在方法中通过this引用。这样本身是没有什么问题,但这样a变量其实就成了一个全局变量,任何testCls的对象都可以直接引用到a,如上例中通过test.a获取到a的值。但很多时候我们并不希望一些对象变量对外公开,即不允许外部程序访问。这应该如何实现呢?如何才能实现一种更好的面向对象编程方式呢?

当然我们可能都会想到这种方式:



var testCls=function(arg1){
        var a=arg1;
        var b=10;
        var alertB=function(){
                 alert(b);
         }
        this.c=5;
        this.setA=function(v){
                 a=v;
         };
        this.alertA=function(){
                 alert(a);
         };
        this.alertB=function(){
                 alertB();
         }
}

var test=new testCls(4);
test.setA(6);
test.alertA();
test.alertB();


这样其实也很好解决了上面提到的问题,但是总又点不雅观,所有变量和方式都混杂在一起看起来很难区分哪些是可以公开访问哪些是不允许公开访问的,哪些是对象的私有变量和公开变量。这样在可读性上就有点差强人意了,我们可以去寻找一种更为雅观的实现方式。

其实只要利用js的闭包特性这个问题就很好搞定了,这也是俺从ext的源码中学习到的。

示例代码如下:



var testCls=function(arg1){
        //对象内部公有变量,不允许外部访问
        var a=arg1;
        var b=10;
        var alertB=function(){
                 alert(b);
         }

        //外部可访问区域
        return {
                 c:5,
                 setA:function(v){
                         a=v;
                 },
                 alertA:function(){
                         alert(a);
                 },
                 alertB:function(){
                         alertB();
                 }
         }
};

var test=new testCls(4);
test.setA(6);
test.alertA();
test.alertB();


同样的实现上面的功能,而且将对象私有变量和公有变量完全分开区域,一目了然,很容易区分出哪些是私有变量哪些是公有变量,这样程序的可读性就得到了大大的提高,而且对对象变量也得到了很好的控制。

如此优美的实现方法,真的让我们不得不叹服js的伟大,当然也要赞一下Extjs的开发者们。