对象的私有成员
原文再续,书接上一回。第一讲里我们提到怎么定义类,怎么创建对象。但在这些对象上创建的属性与方法,都是能被直接访问的,JavaScript并没有提供private,public,protected等属性的权限管理机制。但是,利用闭包我们完全可以实现对象属性和方法的私有化管理。
模仿块级作用域
在讲私有化管理之前,我们必须再讲一下作用域有关的知识。JavaScript只有全局作用域与函数作用域,而没有块级作用域。但我们可以用匿名函数来模仿块级作用域。
在任意作用域中,我们可以用以下代码实现一个短暂的函数作用域:
|
|
只要闭包不作为返回值返回,它的变量对象,执行环境与作用域链就会在执行后销毁。而匿名函数也没有被任何标识符引用,因此在退出执行环境后函数对象也会被垃圾回收。上面的代码在定义了匿名函数的同时马上执行,就能够模拟块级作用域的效果。
这种技术经常用在全局作用域中,避免向全局作用域添加过多的变量和函数。
私有变量
由第二讲知道,某个执行环境中不能访问其作用域链以外的变量和函数。根据这个特点,我们可以把变量放在一个只能由公共接口函数访问的作用域中,这些变量便自然只能被特定的公共接口访问,而不能被直接访问,从而实现了私有化。看一个例子:
|
|
publicMethod函数作为闭包,可以访问privateVarialbe以及privateFunction,但其他函数和变量由于无法看到MyObject这个作用域,所以只能通过publicMethod间接访问,由此实现了私有变量,私有函数以及公共接口。但由于publicMethod是定义在实例上而不是在原型上,因此每创建一个实例都会创建一个publicMethod方法。
静态私有变量
通过将公共接口定义在原型上,可以实现静态私有变量,让所有实例都共享同一个私有变量。
|
|
也是利用了闭包的作用域链的特点,实现静态私有变量,只不过是把公共接口定义在原型对象上。但这样的话私有变量必须被所有实例对象共享,还是要根据需求来选择定义私有变量或者静态私有变量。
模块模式
以上说的都是自定义类型的私有变量和公共方法。但有时候我们不想定义新的类型,在整个系统中只需要对象的一个实例。那么我们可以用模块模式来定义单例对象的私有变量和公共方法。
|
|
也是通过一个模仿块级作用域里定义的私有变量,私有方法以及闭包来实现的。
总结
闭包是实现对象私有变量和私有函数的最重要的技术。关键在于把要保护的变量和函数放在一个特定的作用域内,而这个作用域只存在于公共接口函数的作用域链中。