位置:首頁 > 軟件操作教程 > 編程開發(fā) > JavaScript > 問題詳情

JavaScript 定義閉包

提問人:劉團圓發(fā)布時間:2020-11-25

■知識點

    函數被調用時,會產生一個臨時上下文活動對象,它是函數作用域的頂級對象,作用域內所有私有變量、參數、私有函數等都將作為上下文活動對象的屬性而存在。

    函數被調用后,在默認情況下上下文活動對象會被立即釋放,避免占用系統資源。但是,當函數內的私有變量、參數、私有函數等被外界引用,則這個上下文活動對象暫時會繼續(xù)存在,直到所有外界引用被注銷。

    但是,函數作用域是封閉的,外#無法訪問。那么在什么情況下,外界可以訪問到函數內的私有成員呢?

    根據作用域鏈,內部函數可以訪問外部函數的私有成員。如果內部函數引用了外部函數的私有成員,同時內部函數又被傳給外界,或者對外界開放,那么閉包體就形成了。這個外部函數就是一個閉包體,它被調用后,它的調動對象暫時不被注銷,其屬性會繼續(xù)存在,通過內部函數,可以持續(xù)讀寫外部函數的私有成員。

■實例設計

    典型的閉包體是一個嵌套結構的函數。內部函數引用外部函數的私有成員,同時內部函數又被外界引用,當外部函數被調用后,就形成了閉包,這個函數也稱為閉包函數。

下面是一個典型的閉包結構。

function f(x){                       //外部函數

    returnfunction(y){               //內部函數,通過返回內部函數,實現外部引用

        return x + y;                //訪問外部函數的參數

    };

}

var c = f (5);                      //調用外部函數,獲取引用內部函數

console.log(c(6));                  //調用內部函數,原外部函數的參數繼續(xù)存在

解析過程簡單描述如下。

第1步,在JavaScript腳本預編譯期,聲明的函數f和變量c,先被詞法預解析。

第2步,在JavaScript執(zhí)行期,調用函數f,并傳入值5。

第3步,在解析函數f時,將創(chuàng)建執(zhí)行環(huán)境(函數作用域),創(chuàng)建活動對象,把參數和私有變量、內部函數都映射為活動對象的屬性。

第4步,參數x的值為5,映射到活動對象的x屬性。

第5步,內部函數,通過作用域鏈,引用了參數x,但是還沒有被執(zhí)行。

第6步,外部函數被調用后,返回內部函數,導致內部函數被外界變量c引用。

第7步,JavaScript解析器檢測到外部函數活動對象的屬性被外界引用,無法注銷該活動對象,于是在內存中繼續(xù)維持該對象的存在。

第8步,當調用c,即調用內部函數時,可以看到外部函數的參數x存儲的值繼續(xù)存在,于是也就可以實現后續(xù)運算操作,返回x+y=5+6=ll。

■小結

下面的結構形式也可以形成閉包:通過全局變S引用內部函數,實現內部函數對外開放。

var c;                        //聲明全局變量

function f(x){                //外部函數

    c = function(y){          //內部函數,通過向全局變量開放實現外部引用

        return x + y;         //訪問外部函數的參數

    };

}

f (5);                        //調用外部函數

console.log(c(6));            //使用全局變量c調用內部函數,返回11

繼續(xù)查找其他問題的答案?

相關視頻回答
回復(0)
返回頂部