簡單理解JS中的閉包

定義一個函數(shù)
<pre>
function fn(a,b,...rest){
var arr;
...
function fn2(){
引用外部函數(shù)fn的參數(shù)a,b...rest和局部變量arr

      };

return fn2;

}

fn();
</pre>

當(dāng)調(diào)用fn ()這個函數(shù)時,返回的是fn2()這個函數(shù),fn()的相關(guān)參數(shù)和變量都保存在返回的函數(shù)fn2()中,這種結(jié)構(gòu)就稱為閉包。閉包就是函數(shù)fn2(),即能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。

a,b...rest,arr這些局部變量在fn()這個函數(shù)外是無法被讀取的,但是有時候又想要讀取這些變量,怎么辦呢?

在fn的內(nèi)部再定義一個函數(shù)fn2(),fn2()是可以訪問fn內(nèi)部所有的局部變量的,在內(nèi)部引用局部變量arr,將fn2()作為返回值,即可在外面調(diào)用fn的局部變量。

<pre>
function fn() {
var n = 999;
function fn2() {
console.log(n);
}
return f2;
}
var result = fn();
result(); //999
</pre>

調(diào)用fn()時,返回的并不是n的值,而是函數(shù)fn2(),因此我門要在外面將fn賦給一個函數(shù)result,利用調(diào)用result();返回的值才是n的值。返回的函數(shù)并沒有立刻執(zhí)行,而是直到調(diào)用了result()才執(zhí)行。

另一個例子

<pre>
function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
f(); // 15
</pre>

同樣的,當(dāng)我們調(diào)用lazy_sum()時,返回的并不是求和結(jié)果,而是求和函數(shù)。調(diào)用函數(shù)f
時,才真正計算求和的結(jié)果。

當(dāng)我們調(diào)用lazy_sum()時,每次調(diào)用都會返回一個新的函數(shù),即使傳入相同的參數(shù):
<pre>var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; // false
</pre>

f1()和f2()的調(diào)用結(jié)果互不影響。

于在JavaScript語言中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取內(nèi)部變量,因此可以把閉包簡單理解成“定義在一個函數(shù)內(nèi)部的函數(shù)”。閉包最大的特點,就是它可以“記住”誕生的環(huán)境,比如fn2記住了它誕生的環(huán)境fn,所以從fn2可以得到fn的內(nèi)部變量。在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。

閉包的最大用處有兩個,一個是可以讀取函數(shù)內(nèi)部的變量,另一個就是讓這些變量始終保持在內(nèi)存中,即閉包可以使得它誕生環(huán)境一直存在。

內(nèi)存泄露

因為result();一直存在在內(nèi)存中,而result()的存在依賴于fn,因此也始終在內(nèi)存中,不會在調(diào)用結(jié)束后,被垃圾回收機(jī)制回收,內(nèi)存一直得不到釋放,JS釋放內(nèi)存時就會漏掉這一部分,漸漸越積越多,造成內(nèi)存泄露。

返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會發(fā)生變化的變量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)解析器會率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可以訪問;函數(shù)表達(dá)式則必須...
    coolheadedY閱讀 446評論 0 1
  • 閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高級應(yīng)用都要依靠閉包實現(xiàn)。 一、變量...
    zock閱讀 1,118評論 2 6
  • 郭芳艷 焦點網(wǎng)絡(luò)五期 堅持原創(chuàng)分享第81天 2017.8.11 假期里總是感覺比上班還忙,一個人在家...
    冰山藍(lán)鷹閱讀 106評論 0 0
  • 小朋友們,你們知道嗎?中國五岳名山有哪些?有東岳泰山,南岳衡山,北岳恒山,西岳華山,中岳嵩山。你們知道...
    fdeceb686cba閱讀 623評論 0 0
  • 今天在做一個menu的時候,需要改動item的高度和字體大小顏色。搜索了一下很多方法都不管用,最后是結(jié)合了 sta...
    seven_Android閱讀 8,199評論 4 3

友情鏈接更多精彩內(nèi)容