之前看過廖雪峰老師的閉包講解,當時不明白其中的執行原理,今天在看了渡一的js課程後,明白了閉包的原理。那就舉兩個例子來解釋下。
go物件(global object),全域性環境下建立的執行期上下文,就是全域性作用域。
ao物件(activation object),也叫執行期上下文。在函式被執行前一刻建立,可以稱為是區域性環境、區域性作用域。
scope chain(作用域鏈),被建立的區域性作用域會繼承父級的作用域,形成一條作用域鏈。
再記住一點
但凡是內部的函式被儲存到了外部,它一定生成閉包。內部函式會儲存外部函式的勞動成果,儲存了還沒執行,被放到了外部,而外部的函式自身ao就被內部的閉包函式儲存了。
在乙個函式的執行前有個預編譯,當函式執行時,會建立乙個稱為執行期上下文的內部物件,乙個執行期上下文定義了乙個函式執行時的環境,函式每次執行時對應的執行上下文都是獨一無二的,所以多次呼叫乙個函式會導致建立多個執行上下文,當函式執行完畢,執行上下文被銷毀。
步驟如下:
建立ao物件(activation object),執行期上下文。
尋找函式的形參和內部的變數宣告,將變數宣告和形參名作為ao屬性名,如果有重複則跳過,初始值為undefined。
將實參的值放到形參裡面去,將實參值和形參統一。函式內變數宣告的值傳遞到ao對應的屬性名。
在函式體內部尋找函式宣告,建立ao屬性名,屬性值為函式體。
go除了沒第三步,其它都和ao一樣。
注意!接下來看廖雪峰老師,講python閉包那節課中的兩個例子
def count()
: fs =
for i in
range(1
,4):
def f()
:return i*i
fs.(f)return fs
f1, f2, f3 =
count()
----
----
----
----
----
----
----
----
>>>f1(
)9>>>f2(
)9>>>f3(
)9
按上面的理論來看,在for迴圈結束後,原本的fs = [ ]從乙個空陣列變成了fs = [ f , f , f ],裡面都是一樣的函式名。
並且在迴圈體結束後,i = 3。
此時 f1, f2, f3 = count(),所繼承的東西是一樣的,都是函式名 f。
在這裡,因為函式b被return丟擲來了,它帶著a的ao和go,而在a的ao裡i = 3。
所以在執行f1, f2, f3時,結果就都等於9了。
然後看第二個例子:
def count()
: def f
(j):
def g()
:return j*j
return g
fs =
for i in
range(1
,4):
fs.(f
(i)) # f
(i)立刻被執行,因此i的當前值被傳入f()
return fs
f1, f2, f3 =
count()
----
----
----
----
----
----
----
----
->>>f1(
)1>>>f2(
)4>>>f3(
)9
在count的ao裡,空陣列從fs =[ ]變成了fs = [ f(1) , f(2) , f(3) ]。
這裡就不繼續列出函式f,g的ao了。
直接從return fs開始。這時候f1, f2, f3從陣列中被賦予了三個不同的函式,這三個函式是以陣列的形式,被閉包返回了出來,這三個函式都得到了count的ao和go。
當執行f1, f2, f3時,其實執行的是被返回的g,函式g執行的就是j * j這個表示式。
而由於給陣列末尾新增的是f (i),也就是 f(1) , f(2) , f(3) ,將實參替換形參,就得出了1,4,9的結果。
底層的執行大概就是這樣了,但還有很多東西沒有寫出來,閉包最重要的就是弄明白ao和go的執行步驟、作用域鏈繼承,這些懂了,閉包就沒問題了。
閉包的作用:
1.實現共有變數。
2.可以用作快取。
3.可以實現函式封裝,及屬性私有化。
4.模組化開發,防止汙染全域性變數。
什麼是閉包?直譯器?
外部函式包含內部函式 外部函式具有返回值 返回值是 內部函式名 內部函式引用了外部函式的區域性變數 deffunc def inerfunc pass return inerfunc 裝飾器 函式a是作為引數出現的,函式b接收函式a作為引數 要有閉包的特點 defdecorate func a 10...
什麼是閉包?為什麼使用閉包?閉包的缺點?
閉包 即重用乙個變數,又保護變數不被汙染的一種機制。為什麼使用閉包 全域性變數和區域性變數都具有不可兼得的優缺點。全域性變數 優 可重用,缺 易被汙染。區域性變數 優 僅函式內可用,不會被汙染。缺 不可重用 何時使用 只要即重用乙個變數,又保護變數不被汙染時。如何 3步 1.用外層函式包裹要保護的變...
什麼是閉包
什麼是閉包 閉包說的通俗一點就是打通了一條在函式內部訪問函式內部作用域的通道。正常情況下,函式外部是訪問不了內部作用域變數的,表象判斷是不是閉包 函式巢狀函式,內部函式被return 內部函式呼叫外層函式的區域性變數。優點 可以隔離作用域,不造成全域性渲染。缺點 由於閉包長期駐留記憶體,則長期這樣會...