漫談閉包

1.函數(shù)作為返回值

高階函數(shù)不僅僅可以接受函數(shù)作為參數(shù),還可以把函數(shù)當(dāng)做結(jié)果返回。
例如我們對一個Array求和。

function sum(arr) {
    return arr.reduce(function (x, y) {
        return x + y;
    });
}

sum([1, 2, 3, 4, 5]); // 15

但是當(dāng)他不需要立即求和,可以在后面的代碼里想計算時在計算。可以將這個函數(shù)當(dāng)做返回值。

function lazy_sum(arr){
  var sum = function(){
    return arr.reduce(function(x,y){
        return x+y;
    });
  }
  return sum;
}

所以當(dāng)我們調(diào)lazy_sum時,返回的并不是求和結(jié)果,而是求和函數(shù);

var f = lazy_sum([1,2,3,4,5])   //function sum()
f(); //15

2.閉包

在上面那個例子中,我們在函數(shù)lazy_sum中又定義了函數(shù)sum,并且,內(nèi)部函數(shù)sum可以引用外部函數(shù)lazy_sum的參數(shù)和局部變量,當(dāng)lazy_sum返回函數(shù)sum時,相關(guān)參數(shù)和變量都保存在返回的函數(shù)中,這種稱為“閉包(Closure)”的程序結(jié)構(gòu)擁有極大的威力。

使用閉包需要牢記一點(diǎn):返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會發(fā)生變化的變量。

閉包的作用:
1)讀取函數(shù)內(nèi)部的變量
2)讓這些變量的值始終保持在內(nèi)存中

使用閉包的注意點(diǎn):
1)由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
2)閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

想要理解閉包,關(guān)鍵還是要從代碼中領(lǐng)悟,例子1:

function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
下面這三行分別輸出什么?

先看最外層的fun函數(shù),屬于標(biāo)準(zhǔn)的函數(shù)聲明,返回一個對象,對象為{fun:function(m)},可以看出這個對象為。fun屬性對應(yīng)一個匿名函數(shù),這個匿名函數(shù)形成一個閉包,?使得它可以訪問外部的變量n以及外層函數(shù)fun,所以這里第一個函數(shù)和第三個函數(shù)是相等的。

所以可以得知,最內(nèi)層的return出去的fun函數(shù)不是第二層fun函數(shù),是最外層的fun函數(shù).
第一題:
那么根據(jù)var a = fun(0), a實(shí)際上返回為:{fun:function(m)}
a.fun(1)等價為

function(1){
    return fun(1,n);
}

由于這是一個閉包結(jié)構(gòu),可以訪問外部變量,于是n=0 ,所以返回的為fun(1,0),那么console.log(o)的值為0
同理:
a.fun(2)返回的為fun(2,0),那么console.log(o)的值為0
a.fun(3)返回的為fun(3,0),那么console.log(o)的值為0
第二題:
var b =fun(0).fun(1).fun(2).fun(3) 分別寫出他們的等價函數(shù)為
var b = fun(0) //undefine
var b =fun(0).fun(1)// fun(1,0) //console.log(o)結(jié)果0
var b =fun(0).fun(1).fun(2) //fun(2)=>fun(2,1) //console.log(o)結(jié)果1
var b =fun(0).fun(1).fun(2).fun(3) // =>fun(3,2) //console.log(o)結(jié)果2

第三題:
var c = fun(0).fun(1); c.fun(2); c.fun(3);
var c = fun(0).fun(1);// fun(1,0) //console.log(o)結(jié)果0
c.fun(2) =fun(0).fun(1).fun(2) //fun(2)=>fun(2,1) //console.log(o)結(jié)果1
c.fun(3) =fun(0).fun(1).fun(3) // =>fun(3,1) //console.log(o)結(jié)果1

所以只要掌握三個關(guān)鍵點(diǎn)就能很好的理解這個題目:
1.弄清楚每個函數(shù)的返回值,第一個函數(shù)返回對象,對象里面的函數(shù)返回的仍然是一個函數(shù)。
2.因?yàn)檫@個是閉包結(jié)構(gòu),所以對象里面返回的函數(shù)可以是外部函數(shù)。
3.因?yàn)檫@個是閉包結(jié)構(gòu),所以在內(nèi)部函數(shù)中引用了n的值之后,n的值會存在內(nèi)存中,所以n的值在返回函數(shù)里可以讀取到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內(nèi)容