javascript難點(diǎn)理解-閉包

今天禽捆,看到j(luò)avaScript閉包這一塊的地方,不得不說飘哨,第一次接觸這樣的函數(shù)行為胚想,是很難理解的,也是研究了半天芽隆,才總算理解了閉包這個(gè)牛逼的“東西”浊服;

首先,什么是閉包胚吁,簡單來說牙躺,就是內(nèi)部函數(shù)(inner function)可以訪問外部函數(shù)(outer function)的變量以及參數(shù)(注意inner function不能直接調(diào)用outer function的arguments對象,但可以直接使用參數(shù))囤采;由于述呐,有作用域鏈(scope chain)的存在,導(dǎo)致閉包在outer function即使在被調(diào)用之后蕉毯,inner function依然可以訪問outer function的變量乓搬,這意味著,本來應(yīng)該被銷毀的局部變量代虾,卻一直保留在了內(nèi)存中进肯。

下面看一個(gè)簡單的閉包例子:

function showName(firstName,lastName) {
  var nameInfo="My name is ";

  function makeFullName() {

  return nameInfo+firstName+" "+lastName;

  }

return makeFullName;

}

showName("athan","Zhang")();

//會顯示My name is athan Zhang

上面這個(gè)例子,簡單的解釋了一下內(nèi)部函數(shù)可以直接調(diào)用外部函數(shù)的變量棉磨,以及直接使用外部函數(shù)的參數(shù)江掩。

接下來,看一個(gè)比較復(fù)雜的情況:

function celebrityIDCreator (theCelebrities) {

  var i;

  var uniqueID = 100;

  for (i = 0; i < theCelebrities.length; i++) {

  theCelebrities[i]["id"] = function ()  {

  return uniqueID + i;

  }

}

  return theCelebrities;

}
    var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0},{name:"Willis", id:0}];   

    var createIdForActionCelebs = celebrityIDCreator (actionCelebs);

    var stalloneID = createIdForActionCelebs [0];

    console.log(stalloneID.id());

    var cruiseID = createIdForActionCelebs [1];

    console.log(cruiseID.id());

這個(gè)例子中乘瓤,console打印出的結(jié)果都是103环形。因?yàn)関ar createIdForActionCelebs = celebrityIDCreator (actionCelebs) 這里在調(diào)用外部函數(shù)celebrityIDCreator時(shí),完成了外部函數(shù)里面定義的語句塊的內(nèi)容衙傀,這也意味著抬吟,for循環(huán)也執(zhí)行完畢,數(shù)組theCelebrities的id屬性被賦予了函數(shù)表達(dá)式统抬,但這個(gè)內(nèi)部函數(shù)此時(shí)并沒有被調(diào)用火本。在后面stalloneID.id()顯示調(diào)用內(nèi)部函數(shù)時(shí)危队,返回了uniqueID+i的值,而外部函數(shù)早已調(diào)用完畢钙畔,此時(shí)的i的值茫陆,已經(jīng)是3,所以擎析,無論調(diào)用theCelebrities數(shù)組里面哪一個(gè)對象簿盅,返回的值都是一樣的,這也是閉包存在的一個(gè)問題揍魂,那怎么解決這個(gè)問題呢挪鹏,得看下面的例子。

  function celebrityIDCreator (theCelebrities) {
    var i;

    var uniqueID = 100;

    for (i = 0; i < theCelebrities.length; i++) {

    theCelebrities[i]["id"] = function (j)  { 

    return function () { return uniqueID + j; } () ;

    } (i); 

  }

  return theCelebrities;

  }
  var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0}];

  var createIdForActionCelebs = celebrityIDCreator (actionCelebs);

  var stalloneID = createIdForActionCelebs [0];

  console.log(stalloneID.id); // 100

  var cruiseID = createIdForActionCelebs [1];

  console.log(cruiseID.id);

這個(gè)例子里愉烙,使用了一種Immediately Invoked Function Expression(立刻調(diào)用函數(shù)表達(dá)式)的語法。上面的函數(shù)表達(dá)式function(j){/code/}(i)解取,直接在賦值時(shí)就調(diào)用了步责,而且將i的值賦給了j,同樣閉包里面也用了同樣的語法禀苦,這樣就可以在循環(huán)時(shí)蔓肯,就直接調(diào)用內(nèi)部函數(shù),得到想要的值振乏,這個(gè)例子里面打印的就是100和101蔗包。

有一點(diǎn)需要注意的是,函數(shù)表達(dá)式function(j){/code/}(i)和函數(shù)聲明是不一樣的慧邮,如果在以為函數(shù)聲明時(shí)调限,在函數(shù)后面加上()這個(gè)括號,就是直接調(diào)用函數(shù)误澳,是會出錯(cuò)的耻矮,因?yàn)榫幾g器認(rèn)為這個(gè)是函數(shù)聲明,而不是函數(shù)表達(dá)式忆谓。但是如果用一個(gè)括號裆装,將整個(gè)函數(shù)聲明包起來,編譯器會認(rèn)為是一個(gè)表達(dá)式倡缠,就不會報(bào)錯(cuò)哨免,如下面所示:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昙沦,隨后出現(xiàn)的幾起案子琢唾,更是在濱河造成了極大的恐慌,老刑警劉巖桅滋,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慧耍,死亡現(xiàn)場離奇詭異身辨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芍碧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門煌珊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泌豆,你說我怎么就攤上這事定庵。” “怎么了踪危?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵蔬浙,是天一觀的道長。 經(jīng)常有香客問我贞远,道長畴博,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任蓝仲,我火速辦了婚禮俱病,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘袱结。我一直安慰自己亮隙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布垢夹。 她就那樣靜靜地躺著溢吻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪果元。 梳的紋絲不亂的頭發(fā)上促王,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音而晒,去河邊找鬼硼砰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛欣硼,可吹牛的內(nèi)容都是我干的题翰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诈胜,長吁一口氣:“原來是場噩夢啊……” “哼豹障!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起焦匈,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤血公,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后缓熟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體累魔,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摔笤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垦写。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吕世。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梯投,靈堂內(nèi)的尸體忽然破棺而出命辖,到底是詐尸還是另有隱情,我是刑警寧澤分蓖,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布尔艇,位于F島的核電站,受9級特大地震影響么鹤,放射性物質(zhì)發(fā)生泄漏终娃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一蒸甜、第九天 我趴在偏房一處隱蔽的房頂上張望尝抖。 院中可真熱鬧,春花似錦迅皇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至红氯,卻和暖如春框咙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痢甘。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工喇嘱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塞栅。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓者铜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親放椰。 傳聞我的和親對象是個(gè)殘疾皇子作烟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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

  • 前言 相信很多前端小伙伴在工作和學(xué)習(xí)中,都會或多或少的接觸和了解到匿名函數(shù)和閉包砾医。被這倆知識點(diǎn)所困擾拿撩,也去網(wǎng)上搜索...
    就那ck閱讀 8,963評論 7 21
  • 第一部分 準(zhǔn)入訓(xùn)練 第1章 進(jìn)入忍者世界 js開發(fā)人員通常使用js庫來實(shí)現(xiàn)通用和可重用的功能。這些庫需要簡單易用如蚜,...
    如201608閱讀 1,351評論 1 2
  • 閉包(closure)是Javascript語言的一個(gè)難點(diǎn)压恒,也是它的特色影暴,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一探赫、變量...
    zock閱讀 1,075評論 2 6
  • ● 閉包基礎(chǔ) ● 閉包作用 ● 閉包經(jīng)典例子 ● 閉包應(yīng)用 ● 閉包缺點(diǎn) ● 參考資料 1型宙、閉包基礎(chǔ) 作用域和作...
    lzyuan閱讀 934評論 0 0
  • 第八天 今天的內(nèi)容有兩個(gè),上午講了GreenShock這個(gè)輕量級的動畫引擎的使用并完善了昨天的迷宮游戲期吓。下午完善了...
    一大隊(duì)的人閱讀 317評論 0 1