理解閉包屹逛、立即執(zhí)行函數(shù)、異步和回調(diào)

閉包

什么是閉包

一個(gè)函數(shù)使用了它外面的變量汛骂,這種用法就是閉包罕模。閉包是一個(gè)馬后炮的總結(jié)。

function xxx(){
    var lives = 30
    var bug = 'salkdjaslkdjaslkjd...100MB'   // IE bug
    function die(){
      lives -= 1
      return lives
    }
    return die
}

var dieFn = xxx()
// here
var currentLives = dieFn()

那為何要這樣做呢(搞得這么麻煩):

閉包的作用

閉包常常用來(lái)「間接訪問一個(gè)變量」帘瞭。換句話說淑掌,「隱藏一個(gè)變量」。
因?yàn)槿绻侨肿兞康睿菀妆桓呐淄螅绻蔷植孔兞空┖罚瑒e人又訪問不到。

上面這樣用閉包兽埃,就可以用dieFn()來(lái)修改lives侥钳。

閉包造成內(nèi)存泄露?

內(nèi)存泄露是指你用不到(訪問不到)的變量柄错,依然占居著內(nèi)存空間舷夺,不能被再次利用起來(lái)。

閉包里面的變量明明就是我們需要的變量(lives)售貌,所以不是內(nèi)存泄露

為何有人說是给猾?
因?yàn)?IE。IE 有 bug颂跨,IE 在我們使用完閉包之后敢伸,依然回收不了閉包里面引用的變量。

立即執(zhí)行函數(shù)

什么是立即執(zhí)行函數(shù)

聲明一個(gè)匿名函數(shù)恒削,立即執(zhí)行它池颈,就是立即執(zhí)行函數(shù)

!function (){
    var lives = 30
    console.log(lives)
}.call()

感嘆號(hào)可以換成 + - ~ 等符號(hào),也可以換成括號(hào)钓丰。

那為什么要有這么個(gè)東西(好麻煩)

立即執(zhí)行函數(shù)的作用

只有一個(gè)作用:創(chuàng)建一個(gè)獨(dú)立的作用域躯砰。
這個(gè)作用域里面的變量,外面訪問不到(即避免「變量污染」)携丁。
這個(gè)作用不就恰恰是閉包所需要的嗎W列!梦鉴!
所以之前的函數(shù)可以寫成

!function xxx(){
    var lives = 30
    var bug = 'salkdjaslkdjaslkjd...100MB'   // IE bug
    function die(){
      lives -= 1
      return lives
    }
    return die
}.call()

舉例:

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  liList[i].onclick = function(){
    alert(i) // 為什么 alert 出來(lái)的總是 6李茫,而不是 0、1肥橙、2魄宏、3、4快骗、5
  }
}

因?yàn)樵邳c(diǎn)擊之前i早變成了6娜庇,每個(gè)監(jiān)聽的元素都為6。
那么怎么解決這個(gè)問題呢方篮?用立即執(zhí)行函數(shù)給每個(gè) li 創(chuàng)造一個(gè)獨(dú)立作用域即可

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  !function(ii){
    liList[ii].onclick = function(){
      alert(ii) // 0、1励负、2藕溅、3、4继榆、5
    }
  }(i)
}

在立即執(zhí)行函數(shù)執(zhí)行的時(shí)候巾表,i 的值被賦值給 ii汁掠,此后 ii 的值一直不變。

i 的值從 0 變化到 5集币,對(duì)應(yīng) 6 個(gè)立即執(zhí)行函數(shù)考阱,這 6 個(gè)立即執(zhí)行函數(shù)里面的 ii 「分別」是 0、1鞠苟、2乞榨、3、4当娱、5吃既。

異步+回調(diào)

什么是異步

同步:一定要等任務(wù)執(zhí)行完了,得到結(jié)果跨细,才執(zhí)行下一個(gè)任務(wù)鹦倚。

function taskSync = function(){
  return '同步任務(wù)的返回值'
}

var result = taskSync() // 那么 result 就是同步任務(wù)的結(jié)果
otherTask()             // 然后執(zhí)行下一個(gè)任務(wù)

異步:不等任務(wù)執(zhí)行完,直接執(zhí)行下一個(gè)任務(wù)冀惭。相當(dāng)于給前一個(gè)任務(wù)加個(gè)警報(bào)器震叙,任務(wù)好了再告訴你去執(zhí)行。

function taskAsync = function(){
  var result = setTimeout(function(){
    console.log('異步任務(wù)的結(jié)果')
  }, 3000)
  return result
}

var result = taskAsync() // result 不是異步任務(wù)的結(jié)果散休,而是一個(gè) timer id捐友。不懂?因?yàn)楝F(xiàn)在我是無(wú)法得到3秒后的result溃槐,只會(huì)得到他的定時(shí)器匣砖。
otherTask()              // 立即執(zhí)行其他任務(wù),不等異步任務(wù)結(jié)束

什么情況下需要用到異步昏滴?

如果幾個(gè)任務(wù)互相獨(dú)立猴鲫,其中一個(gè)執(zhí)行時(shí)間較長(zhǎng),那么一般就用異步地方式做這件事谣殊。

什么是回調(diào)

callback 就是(傳給另一個(gè)函數(shù)調(diào)用的)函數(shù)拂共。把括號(hào)里面的內(nèi)容去掉,簡(jiǎn)化成:callback 就是一種函數(shù)姻几。
具體來(lái)講:
當(dāng)一個(gè)函數(shù) A 被作為參數(shù)傳給另一個(gè)函數(shù)時(shí) B宜狐,那么這個(gè)函數(shù) A 就叫做回調(diào)(名詞)。B 中調(diào)用 A 函數(shù)的過程蛇捌,也叫做回調(diào)(動(dòng)詞)抚恒。
那回調(diào)有什么用呢?

回調(diào)的作用

回調(diào)通常用在獲取「異步任務(wù)」的結(jié)果
之前異步的代碼也可寫成如下(為理解起見我簡(jiǎn)化了)

function async(fn){
   setTimeout(function(){
    fn('異步任務(wù)的結(jié)果')
  }, 3000)
  return 
}//函數(shù)聲明

async(function  (xxx){
    console.log(xxx)
}) // 函數(shù)調(diào)用络拌。3秒后執(zhí)行fn,xxx 是異步任務(wù)的結(jié)果
otherTask()             

過程簡(jiǎn)單來(lái)說就是我調(diào)了async函數(shù)俭驮,然后在async函數(shù)里它調(diào)了fn函數(shù)(此時(shí)fn相當(dāng)于是我傳的參數(shù)function),調(diào)用的時(shí)候把'異步任務(wù)的結(jié)果'(此時(shí)'異步任務(wù)的結(jié)果'相當(dāng)于xxx)傳了出來(lái)春贸。
其中function (xxx){ console.log(xxx)}和fn('異步任務(wù)的結(jié)果')都是回調(diào)混萝,一個(gè)是名詞遗遵,一個(gè)是動(dòng)詞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逸嘀,一起剝皮案震驚了整個(gè)濱河市车要,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌崭倘,老刑警劉巖翼岁,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绳姨,居然都是意外死亡登澜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門飘庄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脑蠕,“玉大人,你說我怎么就攤上這事跪削∏聪桑” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵碾盐,是天一觀的道長(zhǎng)晃跺。 經(jīng)常有香客問我,道長(zhǎng)毫玖,這世上最難降的妖魔是什么掀虎? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮付枫,結(jié)果婚禮上烹玉,老公的妹妹穿的比我還像新娘。我一直安慰自己阐滩,他們只是感情好二打,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掂榔,像睡著了一般继效。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上装获,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天瑞信,我揣著相機(jī)與錄音,去河邊找鬼饱溢。 笑死喧伞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绩郎。 我是一名探鬼主播潘鲫,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肋杖!你這毒婦竟也來(lái)了溉仑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤状植,失蹤者是張志新(化名)和其女友劉穎浊竟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體津畸,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡振定,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肉拓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片后频。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖暖途,靈堂內(nèi)的尸體忽然破棺而出卑惜,到底是詐尸還是另有隱情,我是刑警寧澤驻售,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布露久,位于F島的核電站,受9級(jí)特大地震影響欺栗,放射性物質(zhì)發(fā)生泄漏毫痕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一迟几、第九天 我趴在偏房一處隱蔽的房頂上張望消请。 院中可真熱鬧,春花似錦瘤旨、人聲如沸梯啤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)因宇。三九已至,卻和暖如春祟偷,著一層夾襖步出監(jiān)牢的瞬間察滑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工修肠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贺辰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饲化,于是被迫代替她去往敵國(guó)和親莽鸭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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