ExtJS设计模式-模块模式(Module Pattern)

《JavaScript: The Definitive Guide, 5th Edition》一书的8.8章节其中有一段这样的描述:

When you define a nested function, however, the scope chain includes the containing function. This means that nested functions can access all of the arguments and local variables of the containing function.

这句话的主要意思可以理解为:
当你在js中定义一个内部函数时,此内部函数的作用域链将此内部函数包含的所有函数都include到了其中。这就意味着内部函数可以访问所有的包含在其中的函数的参数和本地变量。

在ExtJS的设计中大量利用了这个特点设计代码,获得的最大好处有两点:

1、实现封装

这种写法保证了此方法中定义的内部函数(nested function)与本地变量(local variables)不能被外部访问,同时只允许特权(公有)方法访问这些内部函数或者变量。作用类似于javabean的private成员以及getXXX方法。

2、性能提升(单例模式)-通过模块模式实现

模块模式与单例模式的关系是什么?在提到这个之前不得不提到javascript的单例模式(Singleton)。在javascript中,单例(Singleton)就是指只有一个实例的对象,而不需要用new关键字去创建一个对象实例。单例其实有点类似于java里面的静态类。在javascript中,是以对象字面量的方式来创建单例对象的,也就是以花括号包裹起来的键值对的JSON形式来创建的。例如:
var singletonObj={
    field1:'aaa',
    methodA:function(){
        //code...
    }
}; 


单例模式的目的就是尽可能少的创建对象,最终目的其实就是性能的提升。这点是程序员都清楚,无须多言。

模块模式则是用来对单例对象进行封装,从而能增强单例的可访问性。
以模块模式定义的内部函数(nested function)与变量(local variables)只有单例对象本身的特权(公有)
方法可以访问到,其他外部的任何对象都不可以。
其语法形式如下:
Util = function() { 
	// private
	var A = 1;
	var C = 2;
	// private
	function methodA() {
		// 打印本地变量
		alert("A="+A);
	}
	function methodC(argC) { 
		// 打印参数
		alert("argC=" + argC);
	}

	return {
	         B : 3,
		methodB : function() {
			methodA();
		},
		methodD : function() {
			//打印本地变量
			alert(C);
			//将本地变量作为参数使用
			methodC(C);
		}
	}
}(); //匿名函数立即执行,并且返回


上面的代码中,我们创建了一个匿名函数并赋值给变量Util,然后立即调用这个函数返回可以公开的公有方法和属性的对象实例。在匿名函数内部定义了本地(私有)变量A,C,内部(私有)函数methodA(),methodC()。然后将一个对象实例作为函数值返回,这样返回的对象中只包含可以公开的属性(指变量B)和方法(指函数methodB(),methodD())。

单例对象中公有属性和公有方法的调用与一般对象的属性和方法调用一样,使用点表示法或者方括号语法来调用单例对象的公有成员。

让我们通过以下代码,进一步验证我们的想法。

执行以下代码,会得到TypeError: Util.methodA is not a function
//内部函数不能被访问
Util.methodA();


执行以下代码,会得到ReferenceError: A is not defined
//本地变量不能被访问
alert(A); 


执行以下代码,得到1
//单例模式通过公有方法可以访问内部函数,进而访问本地变量
Util.methodB();


执行以下代码,得到2 C=2 argC=2
//单例模式通过公有方法可以访问内部函数,进而访问本地变量,以及内部函数参数
Util.methodD();


执行以下代码,得到ReferenceError: B is not defined
//公有变量不能直接访问。
alert(B);


执行以下代码,得到3
//公有变量可以通过单例模式访问
alert(Util.B);




所以,模块模式的适用场景:需要对单例进行一些初始化,又需要对私有变量进行封装时。

参考资料链接:
http://www.cnblogs.com/fengmiaosen/archive/2011/01/11/1933219.html

参考文档:
<JavaScript: The Definitive Guide, 5th Edition> By David Flanagan

你可能感兴趣的:(JavaScript,Web,ext)