前端閉包機(jī)制詳解

在談閉包之間,我們先看一下javascript的作用域,我們以函數(shù)舉例。

對(duì)一個(gè)函數(shù)來(lái)說(shuō)它的作用域分為三種:

函數(shù)定義作用域

函數(shù)調(diào)用作用域、

函數(shù)內(nèi)部作用域

以下是一段代碼:

var x="how are you";

var a=0;

function ab(){

? ? ? ?console.log('a=',a);

? ? ? ? console.log('x=',this.x);

}

function ac(){

? ? ? var a=100;

? ? ? var x="I'm fine";

? ? ? ab();

}

ac();

ab();

以下為輸出:

函數(shù)ac的輸出與函數(shù)ab的輸出一致,這是不是很奇怪?函數(shù)ac中定義了同名變量a=100,x="I'm fine",ac中調(diào)用了函數(shù)ab,但函數(shù)ab的輸出并沒(méi)有受到影響。

我們來(lái)看看《javascript權(quán)威指南》中對(duì)閉包的解釋,閉包就是調(diào)用一個(gè)函數(shù)時(shí),如果該函數(shù)內(nèi)函數(shù)體有對(duì)函數(shù)外變量的引用,函數(shù)被調(diào)用時(shí),就是會(huì)將函數(shù)以及函數(shù)引用的變量包裹起來(lái),這就形成了閉包。

我們?cè)賮?lái)看上面的例子,這是js閉包的經(jīng)典示例,我們不難發(fā)現(xiàn),js中對(duì)于函數(shù)的調(diào)用會(huì)回溯到函數(shù)定義時(shí)的作用域,函數(shù)的作用域就是函數(shù)定義的作用域,它和函數(shù)調(diào)用的作用域無(wú)關(guān)。所以無(wú)論函數(shù)ac內(nèi)變量怎么變換,都不會(huì)影響ac內(nèi)函數(shù)ab的輸出。

那么,在函數(shù)調(diào)用作用域與定義作用域不同的情況下,如果我們想讓函數(shù)的掉哦用作用域可以影響函數(shù)的輸出有什么辦法嗎?

答案時(shí)肯定的,方法可以從兩個(gè)方面入手:

方案一:函數(shù)傳參

方案二:改變函數(shù)執(zhí)行上下文

我們先來(lái)看方案一怎么實(shí)現(xiàn)的,以下是示例代碼:

var a='how are you';

function ab(a){

? ? ? console.log('a=',a);

}

function ac(){

? ? ? var a="I'm fine";

? ? ? ab(a);

}

ab(a);

ac(a);

輸出:

通過(guò)輸出可以看出函數(shù)ab的輸出發(fā)生了改變,這是因?yàn)樵诤瘮?shù)ac中變量a被當(dāng)作參數(shù)傳入了函數(shù)ab。再看函數(shù)ac的寫(xiě)法是不是很熟悉,這就是常見(jiàn)的回調(diào)函數(shù)的寫(xiě)法,回調(diào)函數(shù)在異步j(luò)avascript應(yīng)用很多。在函數(shù)ac中函數(shù)ab的調(diào)用,嚴(yán)格意義上算不上閉包,因?yàn)閍c只調(diào)用了ab本身,沒(méi)有連ab外的變量一起調(diào)用。

我們?cè)賮?lái)看改變函數(shù)執(zhí)行上下文怎么實(shí)現(xiàn):

var x="how are you";

function ab(){

? ? ? console.log("x=",this.x);

}

var a={

? ? ? x:"i'm fine"

};

ab();

ab.call(a);

以下是輸出結(jié)果:

ab的輸出更改成功,?在js中使用call,apply以及bind這些方法可以改變函數(shù)執(zhí)行的上下文。

總結(jié),js中的閉包如果想通了其實(shí)很簡(jiǎn)單,就是一個(gè)函數(shù)如果被調(diào)用的話,它不是在調(diào)用它的作用域執(zhí)行的,而是在定義函數(shù)的作用域執(zhí)行的。理論上在不改變函數(shù)執(zhí)行上下文的情況下,只有定義函數(shù)的作用域以及函數(shù)內(nèi)部作用域可以影響函數(shù)的輸出,調(diào)用函數(shù)的作用域要想影響函數(shù)的輸出,只有三個(gè)方法,第一個(gè)調(diào)用函數(shù)作用域以及定義函數(shù)作用域是同一個(gè)作用域(這個(gè)純屬扯淡,是個(gè)人都知道),第二個(gè)是調(diào)用函數(shù)作用域?qū)?shù)傳進(jìn)函數(shù)內(nèi)部作用域,第三個(gè)是通過(guò)apply,call以及bind這些方法改變函數(shù)執(zhí)行的上下文。我現(xiàn)在還想到了第四個(gè)方法,時(shí)間有限,不說(shuō)了,以后在補(bǔ)充。

第一次寫(xiě)技術(shù)文章,難免有很多遺漏的地方,如果這篇文章能有幸給人看到的話,希望您能留下寶貴的意見(jiàn)。

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

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

  • 閉包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。 一、變量...
    zock閱讀 1,119評(píng)論 2 6
  • ● 閉包基礎(chǔ) ● 閉包作用 ● 閉包經(jīng)典例子 ● 閉包應(yīng)用 ● 閉包缺點(diǎn) ● 參考資料 1、閉包基礎(chǔ) 作用域和作...
    lzyuan閱讀 1,041評(píng)論 0 0
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語(yǔ)閱讀 4,105評(píng)論 0 6
  • 為什么你睡了11個(gè)小時(shí)仍然覺(jué)得疲累?為什么你花了好幾萬(wàn)去島國(guó)度假并沒(méi)有增加生活的熱情? 休息的真正含義是什么?是恢...
    小梳子0725閱讀 298評(píng)論 2 6
  • 清晨迎著朝陽(yáng) 夜里披著星光 你瘋狂地奔跑 在逐夢(mèng)的路上 不怕萬(wàn)人阻擋 只怕自己...
    濤心依舊閱讀 734評(píng)論 0 3

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