javascript
闭包 | 浅谈JavaScript闭包问题
1.前言
閉包這個(gè)東西在JavaScript中是一個(gè)很強(qiáng)大的東西,但是在初學(xué)的階段總是被其概念繞暈,搞不清楚到底什么是閉包,感覺(jué)很高深。作者在剛學(xué)的時(shí)候也有一點(diǎn)懵圈,多看幾次就會(huì)有自己的理解。任何東西都沒(méi)有唯一的標(biāo)準(zhǔn),只要適合自己,自己能夠理解的就是正確的。由于作者水平有限,將自己的一些見(jiàn)解拿出來(lái),希望大家能夠提出寶貴的意見(jiàn)。
2.作用域
在正式講閉包之前,我們來(lái)簡(jiǎn)單的說(shuō)一說(shuō)作用域這個(gè)東西。這個(gè)很有助于大家理解后面的閉包。
什么是域?簡(jiǎn)單的說(shuō)就是一個(gè)被圈起來(lái)的地方,也就是變量能夠訪問(wèn)的一個(gè)范圍。
眾所周知,變量的作用域分為全局變量和局部變量。定義在函數(shù)外部的稱為全局變量,在函數(shù)內(nèi)部的稱為局部變量。這里順帶提一下,變量提升這個(gè)玩意兒,也就是和“先聲明后使用差不多的道理”,后面我將會(huì)舉一個(gè)例子來(lái)說(shuō)明。
舉個(gè)例子,全局變量和局部變量:
| 1 2 3 4 5 6 7 8 9 10 11 12 復(fù)制代碼 | var a='wang'; function fun(){var b='huagang';console.log('這是在函數(shù)內(nèi)部的輸出');console.log(a);console.log(b); } fun();//調(diào)用函數(shù)console.log("這是在函數(shù)外部的輸出"); console.log(a); console.log(b); 復(fù)制代碼 |
運(yùn)行結(jié)果:
最后一個(gè)輸出b的時(shí)候拋出了一個(gè)未定義異常,由此可見(jiàn),全局變量(a)在函數(shù)內(nèi)部和外部都是能訪問(wèn)的,但是局部變量不是這樣的,在函數(shù)作用域外是不能訪問(wèn)到函數(shù)內(nèi)部的變量(b)的。這里順帶講一下【變量提升】吧,簡(jiǎn)單的舉一個(gè)例子。
| 1 2 3 4 復(fù)制代碼 | var a; console.log(a); a='wang'; console.log(a) 復(fù)制代碼 |
根據(jù)輸出情況可以看出,第一次輸出a并沒(méi)有報(bào)異常,而是undefined。第二次便能輸出a的值。這就是變量提升的特點(diǎn),在變量還沒(méi)賦值前就拿來(lái)使用了。
3.嵌套函數(shù)的作用域
嵌套函數(shù),顧名思義就是在函數(shù)的內(nèi)部再寫(xiě)一個(gè)或多個(gè)函數(shù)。下面舉一個(gè)例子來(lái)講解一下嵌套函數(shù)的作用域。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 復(fù)制代碼 | function funA(c){var a='wang';function funB(){var b='gang';console.log("在函數(shù)B中的輸出:")console.log(a);console.log(c);console.log(b);}funB();console.log("在函數(shù)A中的輸出:")console.log(a);console.log(c);console.log(b); } funA('hua');//調(diào)用函數(shù)A并傳參 復(fù)制代碼 |
函數(shù)B就是嵌套在函數(shù)A中的嵌套函數(shù),它可以繼承函數(shù)A的變量和參數(shù),但是B中的變量A是不能訪問(wèn)的,就好像B給自己的門(mén)上了鎖,“只進(jìn)不出”,我可以拿你的東西,但是你不可以拿我的東西。B這樣就形成了一個(gè)自己獨(dú)有的封閉空間,這就是一個(gè)閉包。
從不同的角度來(lái)看:從語(yǔ)法結(jié)構(gòu)上看,函數(shù)A包含函數(shù)B;從作用域來(lái)看,函數(shù)B包含函數(shù)A,也就是說(shuō)B能訪問(wèn)的空間比A大。
因此可以想象得出,假如B函數(shù)中還有一個(gè)嵌套函數(shù)X,那么這個(gè)X函數(shù)也是一個(gè)閉包,作用域包含B和A。這樣下去就形成了一個(gè)作用域鏈。
4.閉包
相信通過(guò)上面的講解,大家已經(jīng)懂得了什么是閉包,現(xiàn)在再講講一些關(guān)于閉包的特點(diǎn)或者特性吧。
保存變量
什么是保存變量?加入B這個(gè)閉包需要兩個(gè)變量才能運(yùn)行,但是剛開(kāi)始只傳了一個(gè)參數(shù)進(jìn)去,所以這時(shí)候閉包就會(huì)把這個(gè)變量的值進(jìn)行保存,等待第二個(gè)變量傳入,而不是丟棄這個(gè)變量的值。下面舉一個(gè)例子進(jìn)行說(shuō)明吧。
| 1 2 3 4 5 6 7 8 9 復(fù)制代碼 | function funA(a){function funB(b){return a + b;}return funB;//調(diào)用函數(shù)B的引用 } var x = funA(2); var sum = x(3); console.log(sum);//輸出結(jié)果 5 復(fù)制代碼 |
當(dāng)函數(shù)A傳進(jìn)參數(shù)a=2時(shí),這時(shí)閉包B就將a進(jìn)行保存,等到再傳b=3時(shí)再進(jìn)行計(jì)算。這就是閉包的保存變量。
5.為什么要使用閉包
使用閉包的最大的好處——避免變量的污染。也就是說(shuō)你在閉包中聲明的變量不會(huì)影響在其他地方也使用這個(gè)變量名稱,因?yàn)殚]包將這個(gè)變量鎖在自己的門(mén)里面保護(hù)起來(lái)了,外部是無(wú)法修改的。
| 1 2 3 4 5 6 7 8 9 10 11 復(fù)制代碼 | function funA(){function funB(b){var a = 'wang';//內(nèi)部變量 creturn a+b ;}return funB; } var a = 'hua';//外部變量x,是不能改變閉包B中的變量a的 var sum = funA()(a); console.log(a); console.log(sum); 復(fù)制代碼 |
可以看出,外部變量是不能修改閉包中的變量a的值的,從而保護(hù)了a的值,使其不會(huì)受到污染。
閉包的分享就講到這里啦,我相信大家能夠?qū)﹂]包能夠有一定的了解。當(dāng)然,由于作者水平有限,這只是個(gè)人的見(jiàn)解,有誤的地方還希望多多包涵,或者留言告知我。
我的博客地址:【咕嚕先森的博客】
個(gè)人微信公眾號(hào):【咕嚕有得聊】,歡迎關(guān)注,一起學(xué)習(xí)!
總結(jié)
以上是生活随笔為你收集整理的闭包 | 浅谈JavaScript闭包问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【419天】跃迁之路——程序员高效学习方
- 下一篇: Spring Boot下Druid连接池