定义
【1】【私有变量】
任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数
【2】【特权方法】
如果在函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。而利用这一点,就可以创建用于访问私有变量的公有方法。有权访问私有变量和私有函数的公有方法称为特权方法。
创建方式
【1】【构造函数】
在构造函数内部定义所有私有变量和函数。然后,创建能够访问这些私有成员的特权方法。能够在构造函数中定义特权方法,是因为特权方法作为闭包有权访问在构造函数中定义的所有变量和函数。
[缺点]必须使用构造函数模式来达到目的,且针对每个实例都会创建同样一组方法
function MyObject(){ //私有变量和私有函数 var privateVariable = 10; function privateFunction(){ alert(1) return false; } //特权方法 this.publicMethod = function(){ privateVariable++; return privateFunction(); } } new MyObject().publicMethod();//弹出1
【2】【静态私有变量】
通过在私有作用域中定义私有变量和方法来创建特权方法。
[优点]私有变量和函数由实例共享,增强代码复用
[缺点]每个实例都没有自己的私有变量
(function(){ //私有变量和私有函数 var privateVariable = 10; function privateFunction(){ alert(1) return false; } //在定义该构造函数时并没有使用函数声明,而是使用了函数表达式。且没有使用var关键字,使其成为全局变量。 MyObject = function(){}; //在原型上定义特权方法 MyObject.prototype.publicMethod = function(){ privateVariable++; return privateFunction(); } })(); new MyObject().publicMethod();//弹出1
[另一个例子]
(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; //name变成静态的由所有实例共享的属性 Person.prototype.setName = function(value){ name = value; } })(); var person1 = new Person("Nicholas"); console.log(person1.getName());//"Nicholas" person1.setName("Greg"); console.log(person1.getName());//"Greg" var person2 = new Person("Michael"); console.log(person1.getName());//"Michael" console.log(person2.getName());//"Michael"
作用
【隐藏数据】:利用私有和特权成员,隐藏不应该被直接修改的数据
function Person(name){ this.getName = function(){ return name; } this.setName = function(value){ name = value; }; } var person = new Person("Nicholas"); console.log(person.getName());//"Nicholas" person.setName(‘Greg‘); console.log(person.getName());//"Greg" /*以上代码的构造函数定义了两个特权方法:getnName()和setName()。这两个方法都可以在构造函数外部使用,而且有权访问私有变量name。但在Person构造函数外部,没有任何办法访问name。由于这两个方法都是在构造函数内部定义的,它们作为闭包能够通过作用域访问name。*/
单例
【单例定义】单例是指只有一个实例的对象
【单例创建方式】JavaScript是以对象字面量的方式来创建单例对象的
针对于单例的私有变量和特权方法的两种模式
【1】【模块模式】:使用一个返回对象的匿名函数。在这个匿名函数的内部,首先定义了私有变量和函数。然后,将一个对象字面量作为函数的值返回。返回的对象字面量中只包含可以公开的属性和方法。由于这个对象是在匿名函数内部定义的。因此它的公有方法有权访问私有变量和函数。从本质上讲,这个对象字面量定义的是单例的公共接口。这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时非常有用。
var singleton = function(){ //私有变量和私有函数 var privateVariable = 10; function privateFunction(){ alert(1) return false; } //特权方法和属性 return{ publicProperty: true, publicMethod : function(){ privateVariable++; return privateFunction(); } } }(); singleton.publicMethod();//弹出1
[应用场景]用于管理组件的application对象
var application = function(){ //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponent()); //公共 return{ //返回已注册的数目 getComponentCount : function(){ return components.length; }, //注册新组件 registerComponent : function(component){ if(typeof component == "object"){ components.push(component); } } } }();
【2】【增强模块模式】适合于那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况。
var singleton = function(){ //私有变量和私有函数 var privateVariable = 10; function privateFunction(){ alert(1) return false; } //创建对象 var object = new CustomType(); //特权方法和属性 object.publicProperty = true; object.publicMethod = function(){ privateVariable++; return privateFunction(); }; return object; }();
[应用场景]用于管理组件的application对象的增强模式
var application = function(){ //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponent()); //创建application的一个局部副本,这个变量实际上是application对象的局部变量版 var app = new BaseComponent(); //公共接口 //返回已注册的数目 app.getComponentCount = function(){ return components.length; }; //注册新组件 app.registerComponent = function(component){ if(typeof component == "object"){ components.push(component); } } return app; }();