閉包已經成為近乎神話的概念,它非常重要又難以掌握,而且還難以定義。本文就從閉包的定義說開去
古老定義
閉包(closure),是指函式變數可以儲存在函式作用域內,因此看起來是函式將變數「包裹」了起來
那這樣說來,包含變數的函式就是閉包
//按照古老定義,包含變數n的函式foo就是閉包
function
foo()
console.log
(n)//uncaught
referenceerror: n is
not defined
定義一
閉包是指可以訪問其所在作用域的函式
那這樣說來,需要通過作用域鏈查詢變數的函式就是閉包
//按照定義一的說法,需要通過作用域鏈在全域性環境中查詢變數n的函式foo()就是閉包
var n = 0;
function
foo()
foo();
定義二
閉包是指有權訪問另乙個函式作用域中的變數的函式
那這樣說來,訪問上層函式的作用域的內層函式就是閉包
//按照定義二的說法,巢狀在foo函式裡的bar函式就是閉包
function
foo()
bar();
}foo();
定義三
閉包是指在函式宣告時的作用域以外的地方被呼叫的函式
在函式宣告時的作用域以外的地方呼叫函式,需要通過將該函式作為返回值或者作為引數被傳遞
返回值複製**
//按照定義三的說法,在foo()函式的作用域中宣告,在全域性環境的作用域中被呼叫的bar()函式是閉包
function
foo()
return bar;
}foo()();
可以簡寫為如下表示:
function
foo()
}foo()();
引數
//按照定義三的說法,在foo()函式的作用域中宣告,在bar()函式的作用域中被呼叫的baz()函式是閉包
function
foo()
bar(baz);
}function
bar(fn)
因此,無論通過何種手段,只要將內部函式傳遞到所在的詞法作用域以外,它都會持有對原始作用域的引用,無論在何處執行這個函式都會使用閉包
iife
iife是不是閉包呢?
foo()函式在全域性作用域定義,也在全域性作用域被立即呼叫,如果按照定義一的說法來說,它是閉包。如果按照定義二和定義三的說法,它又不是閉包
var a = 2;
(function
foo())();
最後
閉包定義之所以混亂,我覺得與經典書籍的不同解讀有關。經典定義是犀牛書的原話,定義二是高程的原話
但,歸納起來就是關於乙個函式要成為乙個閉包到底需要滿意幾個條件
嚴格來說,閉包需要滿足三個條件:訪問所在作用域;函式巢狀;在所在作用域外被呼叫
有些人覺得只滿足條件1就可以,所以iife是閉包;有些人覺得滿足條件1和2才可以,所以被巢狀的函式才是閉包;有些人覺得3個條件都滿足才可以,所以在作用域以外的地方被呼叫的函式才是閉包
問題是,誰是權威呢?
深入理解閉包 到底什麼才是閉包
閉包 closure 是指函式變數可以儲存在函式作用域內,因此看起來是函式將變數 包裹 了起來 根據定義,包含變數的函式就是閉包 function foo cosole.log n uncaught referenceerror n is not defined閉包是指可以訪問其所在作用域的函式 按...
什麼是閉包?為什麼使用閉包?閉包的缺點?
閉包 即重用乙個變數,又保護變數不被汙染的一種機制。為什麼使用閉包 全域性變數和區域性變數都具有不可兼得的優缺點。全域性變數 優 可重用,缺 易被汙染。區域性變數 優 僅函式內可用,不會被汙染。缺 不可重用 何時使用 只要即重用乙個變數,又保護變數不被汙染時。如何 3步 1.用外層函式包裹要保護的變...
到底什麼才是使用者體驗度
眾所周知,建立乙個 是需要管理和優化的。有序的管理可以使 穩定的執行和發展,有效的優化可以提公升 的使用者體驗度,獲得更多人的關注,取得更好地盈利資本。最近各大搜尋引擎,特別是不斷的更新演算法並注重強調了使用者體驗度,很多的站長也不斷的發表如何提公升使用者體驗度等話題。但是,遍觀網際網路,提公升使用...