JavaScript 中沒有塊級作用域的概念
因為沒有塊級作用域,所以該函數可以直接運行,而不報錯。
這里有個比較有意思的是,重寫聲明變量 i, 不會報錯,而且也不會改變變量i的值。
JavaScript 中不會提示用戶聲明同一個變量,遇到這種情況,它只會對后續的聲明視而不見。
匿名函數可以模仿塊級作用域,避免在塊級后使用塊級中的變量
模仿塊級作用域中匿名函數的語法如下:
? (function( ){ ?
? ? ? //這里是塊級作用域
? ?})( );
以上代碼定義并立即調用了一個匿名函數。將函數聲明包含在一對圓括號中,表示它實際上是一個函數表達式。而緊隨其后的另一對圓括號表示立即調用這個函數。
另一種表現形式:定義函數的形式來創建
var someFunction = function( ){
? ? ?//這里是塊級作用域
}
someFunction( )
函數表達式后加上()立即執行該函數。
function( ){ } ?為一個函數聲明,聲明后面不能跟圓括號,即function( ) { } ( ) 會出錯。
將函數聲明加上圓括號 即 (function( ){ }) 為函數表達式,在加上()會立即執行該函數表達式。
采用閉包模仿塊級作用域的好處
可以減少閉包占用的內存問題,因為沒有指向匿名函數的引用。只要函數執行完畢,就可以立即銷毀其作用域鏈。
私有變量
嚴格說,JavaScript中沒有私有成員的概念,所有的對象屬性都是公有的。但是具有私有變量的概念。任何在函數中定義的變量,都可以認為是私有變量,函數外部不可以訪問這些變量。私有變量包括函數的參數,局部變量和在函數內部定義的其他函數。
因為在函數內部可以訪問這些私有變量,函數外部不可以訪問。可以利用閉包的特性,在函數內部創建一個閉包,閉包通過自己的作用域鏈中可以訪問這些變量。所以可以實現創建用于訪問私有變量的公有方法。
特權方法?
有權訪問私有變量和私有函數的公有方法稱為特權方法。
有兩種方式可以創建特權方法
1.構造函數中定義特權方法
以上代碼的構造函數中定義了一個特權方法:publicFunction( )。這個方法可以在構造函數外部使用。而且有權訪問私有變量 privateNum 和私有方法privateFunction。在構造函數外部,沒有辦法訪問私有變量和私有方法。
變量privateNum 和函數 privateFunction 在MyFunctionObject中每個實例都不相同,因為每次調用構造函數都會重寫創建這個變量和方法。構造函數中定義的特權方法的缺點是,必須使用構造函數模式來達到這個目的,針對每個實例都會創建同一組新方法。可以使用靜態私有變量來實現特權方法避免這個問題。
靜態私有變量
通過私有作用域中定義私有變量和函數,同樣可以創建特權方法
該模式創建了一個私有作用域,并在其中封裝了一個構造函數,及相應的方法。
在私有作用域中首先定義私有變量,然后定義構造函數,注意,這個地方定義構造函數并沒有使用函數聲明,而是使用函數表達式,函數聲明只能創建局部變量不是我們想要的。同時在聲明Person沒有使用Var,可以自動添加到全局變量中。公有方法是在原型上定義的。由于原型上的定義方法,所有的實例都使用同一個函數,而這個特權方法,作為一個閉包,總是保存著對包含作用域的引用。
可以看出這種方式創建靜態私有變量會因為使用原型而增進代碼復用,但每個實例都沒有自己的私有變量。
模塊模式
道格拉斯所說的模塊模式是為單例創建私有變量和特權方法。 JavaScript是以對象字面量的方式創建單例對象。