定義
【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; }();
目錄連結
【2】函式表示式
【3】閉包
【5】匿名函式模仿塊級作用域