深入了解Javascript模块化编程

 模块化编程是一种非常常见Javascript编程模式。它一般来说可以使得代码更易于理解,但是有许多优秀的实践还没有广为人知。在这篇文章中,我将会回顾一下js模块化编程的基础,并且将会讲到一些真的非常值得一提的进阶话题,包括一个我认为是我自创的模式。

基础

我们首先简单地概述一下,自从三年前Eric Miraglia(YUI的开发者)第一次发表博客描述模块化模式以来的一些模块化模式。如果你已经对于这些模块化模式非常熟悉了,大可以直接跳过本节,从“进阶模式”开始阅读。

匿名闭包

这是一种让一切变为可能的基本结构,同时它也是Javascript最棒的特性。我们将简单地创建一个匿名函数并立即执行它。所有的代码将跑在这个函数内,生存在一个提供私有化的闭包中,它足以使得这些闭包中的变量能够贯穿我们的应用的整个生命周期。


(function(){
// ... all vars and functions are in this scope only
// still maintains access to all globals}());


注意这对包裹匿名函数的最外层括号。因为Javascript的语言特性,这对括号是必须的。在js中由关键词function开头的语句总是会被认为是函数声明式。把这段代码包裹在括号中就可以让解释器知道这是个函数表达式

全局变量导入

Javascript有一个特性叫做隐式全局变量。无论一个变量名在哪儿被用到了,解释器会根据作用域链来反向找到这个变量的var声明语句。如果没有找到var声明语句,那么这个变量就会被视为全局变量。如果这个变量用在一句赋值语句中,同时这个变量又不存在时,就会创建出一个全局变量。这意味着在匿名闭包中使用或创建全局变量是很容易的。不幸的是,这会导致写出的代码极难维护,因为对于人的直观感受来说,一眼根本分不清那些是全局的变量。

幸运的是,我们的匿名函数提供了简单的变通方法。只要将全局变量作为参数传递到我们的匿名函数中,就可以得到比隐式全局变量更清晰快速的代码了。下面是示例:

(function($,YAHOO){
// now have access to globals jQuery (as $) and YAHOO in this code}(jQuery,YAHOO));

 

模块导出

有时你不仅想要使用全局变量,你还想要声明它们,以供反复使用。我们可以很容易地通过导出它们来做到这一点——通过匿名函数的返回值。这样做将会完成一个基本的模块化模式雏形,接下来会是一个完整的例子:

varMODULE=(function()
{
varmy={},
privateVariable=1;
functionprivateMethod(){// ...}
my.moduleProperty=1;
my.moduleMethod=function(){// ...};
returnmy;}());

 

注意我们已经声明了一个叫做MODULE的全局模块,它拥有2个公有的属性:一个叫做MODULE.moduleMethod的方法和一个叫做MODULE.moduleProperty的变量。另外,它还维护了一个利用匿名函数闭包的、私有的内置状态。同时,我们可以很容易地导入需要的全局变量,并像之前我们所学到的那样来使用这个模块化模式。

进阶模式

上面一节所描述的基础已经足以应对许多情况,现在我们可以将这个模块化模式进一步的发展,创建更多强大的、可扩展的结构。让我们从MODULE模块开始,一一介绍这些进阶模式。

放大模式

整个模块必须在一个文件中是模块化模式的一个限制。任何一个参与大型项目的人都会明白将js拆分多个文件的价值。幸运的是,我们拥有一个很棒的实现来放大模块。首先,我们导入一个模块,并为它添加属性,最后再导出它。下面是一个例子——从原本的MODULE中放大它:

varMODULE=(function(my){
my.anotherMethod=function(){
// added method...
};
returnmy;}
(MODULE));

 

我们用var关键词来保证一致性,虽然它在此处不是必须的。在这段代码执行完之后,我们的模块就已经拥有了一个新的、叫做MODULE.anotherMethod的公有方法。这个放大文件也会维护它自己的私有内置状态和导入的对象。

宽放大模式

我们的上面例子需要我们的初始化模块最先被执行,然后放大模块才能执行,当然有时这可能也不一定是必需的。Javascript应用可以做到的、用来提升性能的、最棒的事之一就是异步执行脚本。我们可以创建灵活的多部分模块并通过宽放大模式使它们可以以任意顺序加载。每一个文件都需要按下面的结构组织:

varMODULE=(function(my){
// add capabilities...
returnmy;
}(MODULE||{}));

 

在这个模式中,var表达式使必需的。注意如果MODULE还未初始化过,这句导入语句会创建MODULE。这意味着你可以用一个像LABjs的工具来并行加载你所有的模块文件,而不会被阻塞。

紧放大模式

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信