理解JavaScript模块模式

 

  JavaScript模块模式原先是由Yahoo的Douglas Crockford提出的,在Yahoo的博文中有关于此模式的描述(http://yuiblog.com/blog/2007/06/12/module-pattern/),这种模式也应用到了YUI组件开发中,最核心的理念是用JavaScript的”类”封装私有和公有的属性和方法。

  这种模式是JavaScript实现中的一种最佳实践方式.能够清晰地表达JavaScript面向对象概念 。它不允许开发人员定义全局变量去”污染”全局对象。通过增强这种模式,可以提高web的性能,同时这种模式实现的JavaScript代码也是易于维护的。

  在JavaScript程序设计语言中,函数可以作为一个模块,在某些情况下,需要创建的是单例对象,而不是创建一个类的实例。在模块的内部,公共接口可以访问模块中的私有变量以及私有方法。这些公共接口函数又叫做特权方法(Privileged Methods)

  许多JavaScript实现的应用程序使用的都是单例,因此JavaScript模块模式应用得就比较多。因此,创建一个匿名函数用来返回一个字面量对象包装的特权方法集,由于闭包原则,这些特权方法有权访问到匿名函数中的变量已经方法,这就是模块模式。

为什么使用模块模式?

1. 通过此模式可以把面向对象的一些理念在JavaScript语言中表述得更清晰,比如封装的思想。

2. 通过特权方法可以访问到私有变量以及私有方法,因为你不希望这些私有变量以及方法被外部无限制地访问。

使用此模式时需要注意的就是闭包的实现,即返回的特权方法。

自执行函数

在模块模式中,通过自执行方法来创建全局单例对象,通常创建的单例对象都是全局的。自执行方法通常用来创建匿名函数的。看一个例子:

 

(function(){

    //函数体的实现

})();


理解了上面的自执行函数后,下面看一下模块模式

 

var jsModule = function(){//全局单例对象

    var privateVar = "Foo";

    var privateMethod = function(){

        return privateVar;

    };

    return {

        printVar: function(){

            return privateMethod();

        }

    };

}();//自执行函数

console.log(jsModule.printVar());
  

也可以这样:

var jsModule = function(){

    var privateVar = "Foo";

    var privateMethod = function(){

        return privateVar;

    };

    var obj =  {//注意这里的字面量对象可以是通过工厂模式创建的对象

        printVar: function(){

            return privateMethod();

        }

    };

    obj.appendBar = function(){//对返回的对象进行扩展。

        return "Bar";

    }

    return obj;

}();

console.log(jsModule.printVar());//Foo

console.log(jsModule.appendBar());//Bar


创建子模块

在原有模块基础上加强模块功能

 

var jsModule = (function(){

    var privateVar = "Foo";

    var privateMethod = function(){

        return privateVar;

    }

    return {

        printVar: function(){

            return privateMethod();

        }

    }

})();

jsModule.subModule = function(){//在现有模块基础上添加子模块,相当于给一个字面量对象添加一个属性,这个属性值还是一个字面量对象

    var anotherPrivateVar = "Bar";

    var sayWord = function(str){

        switch(str)

        {

            case "Foo":

                return "Foo Bar";

            default:

                return "Hello World";

        }

    };

    return {

        say: function(){

            return sayWord(jsModule.printVar());

        }

    }

}();

console.log(jsModule.subModule.say());


扩展模块

通过把现有模块包装到一个新的模块来扩展现有模块。可以访问现有模块中的方法,以及重写现有模块方法:

 

var newJsModule = function(super_module){

    var parent_module = super_module;//下面就可以访问父模块特权方法了

    parent_module.printVar = function(){//重写父模块方法

        return "Bar";

    };

    var privateMethod2 = function(){

        return "Hello JavaScript";

    };

    return {

        newPrintVar: function(){

            return parent_module.printVar();//访问父模块方法

        }

    }

}(jsModule);//通过传递已有模块来扩展该模块,定义完匿名函数就立刻执行

console.log(newJsModule.newPrintVar());


模块模式的缺点

  1. 如果想改变属性和方法的可见性,那么就要修改每一处使用到这些属性以及方法的地方
  2. 在模块后来添加的方法中无法访问到原模块中的私有属性以及方法,可以通过创建子模块或者扩展模块来扩展功能。

 

var jsModule = function(){

    var privateVar = "Foo";

    var privateMethod = function(){

        return privateVar;

    };

    return {

        printVar: function(){

            return privateMethod();

        }

    };

}();

console.log(jsModule.printVar());

jsModule.newMethod = function(){

    return privateMethod();ReferenceError, privateMethod is not defined()

}

console.log(jsModule.newMethod());


小结

没有完美的解决方案,只有合适的。通过对象模式可以写出大型复杂的JavaScript程序,YUI的开发都用到此模式,所以在平时的开发中还是值得借鉴的。

转载于:https://www.cnblogs.com/chinatea/archive/2011/12/30/JavaScript_Module_Pattern.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值