定义
【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】【静态私有变量】
【优点】 私有变量和函数有实例共享,增强代码复用
【缺点】每个实例都没有自己的私有变量
// var MyObject = function() {};
(function() { // 私有变量和私有函数 var privateVAriable = 10; function privateFunction() { alert(1); return false; } //定义全局的构造函数 MyObject() 。 MyObject = function() {}; //在该构造函数的原型上定义特权方法 MyObject.prototype.publicMethod = function() { privateVariable++; return privatefunction(); } } )(); new MyObject().publicMethod(); //弹出1
上述代码中构造函数处于某私有作用域中,特权方法 用来返回 私有作用域的 私有函数和私有变量,构造函数是否定义在私有作用域内无关紧要,。
当实例化的时候,获取的都是私有作用域的私有变量和私有函数,因此,所有实例公用一套私有变量和私有函数。
【另一个例子】
(function () { var name = ""; Person = function(value) { name = value; };
// getName和setName都为特权方法,涉及了闭包。 Person.prototype.getName = function() { return name; }; // name变成静态的 由所有实例共享的属性 Person.prototype.setName = functoin(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("Michae1"); console.log(person1.getName()); //"Michae1" console.log(person2.getName()); //"Michae1"
作用
【隐藏数据】:利用私有和特权成员,隐藏不应该被直接修改的数据。
function Person(name) { this.getName = function() { return name; }; this.setName = function() { name = value; }; } var person = new Person('Nicholas'); console.log(person.getName()); //'Nicholas' person.setName('Greg'); console.log(person.getName()); //'Greg'
以上代码的构造函数定义了两个特权方法: getName() 和setName() 。这两个方法都可以在构造函数外部使用,而且有权访问私有变量name。但在Person构造函数外部,没有任何方法访问name。由于这两个方法都是在构造函数内部定义的,他们作为闭包能够通过作用域访问name
单例
【单例定义】单例是指只有一个实例的对象
【单例创建方式】JavaScript是以对象字面量的方式来创建单例对象的
var single = {
publicProperty: true,
publicMethod: function() {},
};
针对单例的私有变量和特权方法的两种模式
【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 = functoin() { // 私有变量和函数 var components = new Array(); // 初始化 -- 就是先注册一个组件 components.push(new BaseComponent); // 公共 return{ //返回已注册的数目 getComponent:function() { return components.length; }, // 注册新组件 registerComponent : function(component) { if (typeof component == "object") { components.push(component); } } } }
【2】【增强模块模式】适合于那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况。
var single = function() { // 私有变量和私有函数 var privateVariable = 10; function privateFunction() { alert(1); return false; } // 创建对象 var object = new CustomType(); // 特权方法和属性 object.publicProperty = true; object.publicMethod = function() { pricateVariable++; 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.reqisterComponent = function() { if (typeof component == "object") { components.push(component); } } return app; }
出处:小火柴的蓝色理想