1. 程式人生 > 實用技巧 >scope(域),js的閉包

scope(域),js的閉包

scope(域)


這兩個概念必需一起理解,閉包是講編譯方式,scope是講閉包的原理 ,相輔相成的。
由於js有預編譯的階段,然後再是執行階段。在預編譯階段,會根據var和function關鍵字找到宣告的變數和函式,然後抽出來。在執行階段,根據程式碼定義賦值的地方初始化var宣告的變數,在呼叫函式時,會建立新的scope(域),scope存在的內容就是預編譯階段抽出的var宣告和變數和function宣告的函式,注意儲存的是引用,裡面的內容可能會被程式碼修改。

函式在定義的時候就會建立一個scope,儲存當前環境下的資料,在執行函式時,內部會建立一個新的scope,這個scope內的資料是根據程式碼的執行不斷變化的。這個新的scope當前執行的函式可以有一份,如果函式返回另一個函式,那另一個函式在定義的會建立一個scope。
總結一句話,函式定義時,會根據當前環境建立一個scope並保持關係,在函式執行時建立一個新的scope,2個scope是父子依賴關係,在JavaScript中所有的域都是並且只能是被函式域(function scope)所建立,它們不能被for/while迴圈或者if/switch表示式建立

第一個scope內部資料為{name:underfined, test1:function(){...}}由於執行第一個test1()時,name還沒初始化,所以為underfined),第二個scope是函式體內部scope為{c=3},2個scope構建scope鏈,查詢變數,先從內部開始找,找不到向上遊找,直到找到全域性scope。

理解scope要點
-函式在定義時,會生成一個scope
-函式在執行時,會建立一個新的scope,也叫做本地scope,同時建立一個連結向上父scope,scope域內維護的資料是預編譯時篩選的var和function宣告的東西。不是環境執行時上下文環境變數
- scope可以用於建立函式時儲存函式定義時一些資料

this變數

對於this,我們可以理解為:特殊的Scope引用變數,其指向當前函式的執行環境Scope(並不是定義時的Scope)

可以使用apply改變執行上下文時環境,比如doit.apply(funderfined, "666")

閉包

閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高階應用都要依靠閉包實現
我覺得閉包就出現就是為了儲存執行環境時一些變數資料。
有權訪問另一個函式作用域內變數的函式都是閉包.

閉包就是將函式內部和函式外部連線起來的一座橋樑

閉包就是能夠讀取其他函式內部變數的函式

閉包的用途

1一個是前面提到的可以讀取函式內部的變數

2另一個就是讓這些變數的值始終保持在記憶體中(會一直在記憶體中,這也是閉包的缺點,容易造成記憶體洩漏)

我們一般喜歡通過一個函式返回另一個函式的閉包形勢,將外部資料變成函式的區域性變數,然後返回的函式在定義時建立一個scope,scope儲存有這個區域性變數值,這樣一來,這個返回的函式就會一直儲存傳入的資料。

使用閉包的注意點

1)由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除。

2)閉包會在父函式外部,改變父函式內部變數的值。所以,如果你把父函式當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函式內部變數的值

閉包有3個特性:

①函式巢狀函式

②函式內部可以引用函式外部的引數和變數

③引數和變數不會被垃圾回收機制回收

閉包的步驟:

1.函式內部巢狀子函式,

2.子函式得到父函式的值。

3.把內層函式返回出去