到底什麼才是閉包

2021-08-04 02:48:45 字數 1710 閱讀 1637

閉包已經成為近乎神話的概念,它非常重要又難以掌握,而且還難以定義。本文就從閉包的定義說開去

古老定義

閉包(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.用外層函式包裹要保護的變...

到底什麼才是使用者體驗度

眾所周知,建立乙個 是需要管理和優化的。有序的管理可以使 穩定的執行和發展,有效的優化可以提公升 的使用者體驗度,獲得更多人的關注,取得更好地盈利資本。最近各大搜尋引擎,特別是不斷的更新演算法並注重強調了使用者體驗度,很多的站長也不斷的發表如何提公升使用者體驗度等話題。但是,遍觀網際網路,提公升使用...