2-2 Scope與Closure

Scope與Closure

(看了一下註解,發現漏掉這個主題了XD...看起來擺這裡比較適合)

要快速理解Javascript的Scope(變數作用範圍)原理,只要記住他是Lexical Scope就差不多了。簡單地說,變數作用範圍是依照程式定義時(或者叫做程式文本?)的上下文決定,而不是執行時的上下文決定。

為了維護程式執行時所依賴的變數,即使執行時程式運行在原本的scope之外,他的變數作用範圍仍然維持不變。這時程式依賴的自由變數(定義時不是local的,而是在上一層scope定義的變數)一樣可以使用,就好像被關閉起來,所以叫做Closure。用程式看比較好懂:

function outter(arg1) {
  var free_variable1 = 3;//arg1及free_variable1對inner函數來說,都是自由變數
  return function inner(arg2) {
    var local_variable1 =2;//arg2及local_variable1對inner函數來說,都是本地變數
    return arg1 + arg2 + free_variable + local_variable1;
  };
}

var a = outter(1);//變數a 就是outter函數執行後返回的inner函數
var b = a(4);//執行inner函數,執行時上下文已經在outter函數之外,但是仍然能正常執行,而且可以使用定義在outter函數裡面的arg1及free_variable1變數
console.log(b);//結果10

在Javascript中,scope最主要的單位是函數(另外有global及eval),所以有可能製造出closure的狀況,通常在形式上都是有巢狀的函數定義,而且內側的函數使用到定義在外側函數裡面的變數。

Closure有可能會造成記憶體洩漏,主要是因為被參考的變數無法被垃圾收集機制處理,造成佔用的資源無法釋放,所以使用上必須考慮清楚,不要造成意外的記憶體洩漏。(在上面的例子中,如果a一直未執行,使用到的記憶體就不會被釋放)

跟透過函數的參數把變數傳給函數比較起來,Javascript Engine會比較難對Closure進行最佳化。如果有效能上的考量,這一點也需要注意。

Comments