对于初学者有效的JavaScript设计模式(3)

去年的这个时候看了一遍这个文章,说实话,看了等于没看。1、看了也没有理解,2、看了也没有在实际中用到,3、看了就忘了

今年的这个时候又看到这个文章,隐隐约约觉得,“呀,我看过,还翻译过”,但是却对内容完全想不起来了。去年看这个模块的时候,看的云里雾里的,完全没懂。

现在嘛,再来看这个模式,觉得豁然开朗啊,因为自己也就是在用这个模式来构建的代码。

四、模块模式 

模块模式是基于对象字面量的形式,所以首先来看看对象字面量。

对象字面量

对象字面量,一个对象由 一组以逗号分割的名称/值对 包裹在一对{}中组成。

名称可以使字符串或标识符,在最后一对名/值后不能加逗号。

模块模式

在传统的软件工程中,模块模式最初被定义为一种在类中能够同时提供私有和公共封装的方法。

在JavaScript中,我们可以用模块模式来模拟这样的类,把私有/公有的方法和变量都放在一个单一的类中,从而与全局部分分开。这样可以减少函数名之间冲突的可能性。

在JavaScript中没有真正意义上的“私有”,它不像其他一些传统的语言,它不具有访问修饰符。变量不能技术上声明为“公有”或“私有”。在模块模式中,声明的变量和方法只能在模块中用,这都归功于闭包。在return对象中声明的变量和方法可以对任何人使用。

例子

其他部分的代码是不能直接使用incrementCounter()和resetCounter()函数的。变量counter是一个与全局隔离的变量,它就像私有变量一样,只存在于模块中。所以也只有我们的两个方法incrementCounter()和resetCounter()能够使用它。

 

使用模块模式的时候,我们可以用一个简单的模板来开始。下面的这个模板包括了命名空间,共有和私有变量:

 

下面的例子我们可以看到用这种模式实现的“购物篮”。模块本身自己包含了一个全局的变量basketModule. basket数组在模块中是一个私有变量,所以应用的其他部分不能直接读取它。它只存在于这个闭包中,所以能够访问它的方法是那些在闭包中的方法,比如(addItem(),getItem()等)

在这个模块中,你可以看到我们返回了个object. 它自动的分配到basketModule ,所以我们能够像下面这样与它交互:

上面的方法在basketModule这个命名空间中。

 

模块模式的变化

1、 Import mixins

这种方法展示了全局对象能够作为模块匿名函数的变量。这样使得我们能够有效地“引入import”它们,并且在局部重命名它们。

2、Export

这个变换允许我们声明全局变量而不需要使用它们,能够简单的支持全局引入的概念,见下一个例子

调用的时候,直接myModule.publicProperty / myModule.publicMethod()

工具和一些框架模块会这样用到。

 

优点与缺点

优点:

(1)我们能看出单体模式的用处,但是为什么模块模式是个好的选择?对于初学者(JavaScript角度来说)来说,从面向对象的背景出发比一个好的封装的想法对未来的开发道路要好的多。

(2)支持私有数据。所以在模块模式中,公共的部分可以访问到私有部分的数据;而模块以外的地方就不能访问到私有部分的数据。

缺点:

模块模式中对于私有和公有变量不能的处理方式,使得我们如果要改变变量的属性(私有/共有),不得不改变每个用到此变量的地方。

我们同样不能访问在对象后面添加的私有变量。这意味着,在多数情况下,模块模式也是有用的。当正确使用的时候,也是有潜力提高我们应用程序的结构的。

其他缺点包括不能对私有成员创建自动的单元检测脚本,bugs需要立即修复时无法在控制台里立即实现(因为无法访问到私有成员)。开发者不能方便地对私有变量进行扩展。所以私有变量会变得不是很灵活。

 

另外,

The Revealing Module Pattern

是Christian Heilmann版本的模块模式

这种模式对模块模式的改进之处在于,可以在私有的范围中简单的定义我们的函数和变量,然后返回一个匿名的对象,其中指向我们希望共有的函数。例如:

优点:

使得脚本的语法更加一致。模块的最后也更加的清晰,公共部分更加有可读性。

缺点:

如果一个私有函数指向一个公有函数,如果需要补丁的话,公有的功能不能被覆盖。因为私有的函数还是会继续指向私有的实现,而模式不会应用到公有的成员。

公有的对象成员指向私有的变量同样没有覆盖。

上面两句话太绕了,咨询了别人以后,我的理解就是不要试图去改变模块里面的东西。

比如用

myRevealingModule.setName = function(){

    alert("aaa");

}

也不会使得publicSetName有任何改变.

所以这种方法创建的模块与用传统的方式更加的脆弱~

 

 

 

posted @ 2012-07-03 17:03  hlily  阅读(386)  评论(0编辑  收藏  举报