JavaScript中没有私有成员的概念,不过,有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量。如果在这个函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量,利用这一点,就可以创建用于访问私有变量的公用方法,也就是特权方法。
可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式和增强的模块模式来实现单例的特权方法。
构造函数模式
以下全部代码来自《JavaScript高级程序设计》
function Persom(name){
this.getName=function(){
return name;
};
this.setName=function(value){
name=value;
};
}
var person=new Person("zxj");
alert(person.getName()); //zxj
person.setName("Greg");
alert(person.getName()); //Greg
在以上构造函数中定义了两个特权方法:getName()和setName()。这两个方法都可以在函数外部使用,而且都有权访问私有变量name,并且只有这一种方法访问。
构造函数法:缺点,每个实例都会创建一个特权方法,代码复用性差,跟之前创建对象使用构造函数模式时一样的问题。
静态私有变量
(function(){
var name = "";
Person = function(value){
name = value;
};
Person.prototype.getName = function(){
return name;
};
Person.prototype.setName = function (value){
name = value;
};
})();
var person1 = new Person("zxj");
alert(person1.getName()); //"zxj"
person1.setName("Greg");
alert(person1.getName()); //"Greg"
var person2 = new Person("Michael");
alert(person1.getName()); //"Michael"
alert(person2.getName()); //"Michael
静态私有变量法:自调用函数,内部产生私有作用域,可定义私有属性和方法,嵌套一个全局构造函数,可访问内部私有属性(闭包),又可以被外部访问(全局函数),用原型模式为构造函数添加特权方法(跟构造函数一样是闭包,能访问name),就解决了代码复用问题,但是每个实例没有了自己的私有变量,因为全局构造和特权方法访问的私有变量是在匿名函数变量对象中找到的,每个实例都共享这一个私有变量(下面的name),一变全变,不管是新实例化,还是setName,都会改变所有实例的name。
以上两种方法是实现自定义类型的特权方法,下面介绍两种实现单例类型的特权方法。
模块模式
单例就是指,只有一个实例的对象。
JavaScript是以对象字面量的方式创建单例对象的。
var singlton={
name:value,
method:function{
//这是方法的代码
}
}
模块模式通过单例添加私有变量和特权方法能够使其得到增强
var singlton=function{
//私有变量和私有函数
var privateVaiable=10;
function privateMethod(){
return false;
};
//公有/特权方法
return {
publicProperty:true,
piblicMethod:function(){
privateVaiable++;
return privateMethod();
}
}
}();
这个模块使用了一个返回对象的匿名函数。在这个匿名函数内部,首先定义了私有变量和函数。然后,将一个对象字面量作为函数的值返回。返回的对象字面量中只包含可以公开的属性和方法。从本质上讲,这个对象字面量定义的是单例的公共接口。
这种模式对于需要对单例对象进行初始化,并维护私有变量非常有用,angular 中的服务都是这种单例,先定义私有变量,再提供方法接口。
增强模块模式
就是在模块模式的基础上,不过返回的不是字面量对象,是一个明确需要返回的自定义类型的单例。
对上面模块模式的代码进行修改就可以增强
var singlton=function{
//私有变量和私有函数
var privateVaiable=10;
function privateMethod(){
return false;
};
//创建对象
var object=new CustomType();
//公有/特权方法
object.publicProperty=true;
object.piblicMethod=function(){
privateVaiable++;
return privateMethod();
};
//返回这个对象
return object;
}();