日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript闭包,你大爷永远是你大爷

發(fā)布時(shí)間:2024/9/21 javascript 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javascript闭包,你大爷永远是你大爷 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

閉包 what 's the fuck

閉包,是什么鬼,誰學(xué)誰都腦進(jìn)水!

我會(huì)用5W3H1TS的方式,去講閉包


1. what

一個(gè)函數(shù),記住自己定義時(shí)的“詞法作用域”,就產(chǎn)生了閉包

即使此函數(shù)在其他地方執(zhí)行!

上一個(gè)“詞法作用域”的 例子 ,程序走起,與JAVA的動(dòng)態(tài)作用域,有本質(zhì)不同

因果鏈思維中,這個(gè)詞法作用域就是“已知的因?yàn)椤?#xff0c;通過這個(gè)因?yàn)?#xff0c;我們往下想,才能想通,閉包這個(gè)結(jié)果

例子:

var fn1; function aa(){var t1 = 100;fn1 = function(){console.log(t1);} } var t1 = 200; aa(); fn1(); 復(fù)制代碼

結(jié)果是打印 100,

結(jié)論: 可以確定,JS真的是詞法作用域

我是按“例子-結(jié)論”的思維去做的


2. why

閉包是解決函數(shù)式語言的一個(gè)問題的一種技術(shù),這個(gè)問題就是如何保證將函數(shù)當(dāng)做值創(chuàng)造并傳來傳去的時(shí)候函數(shù)仍能正確運(yùn)行。

閉包實(shí)現(xiàn)的例子,其中一種用法: 模擬塊作用域,不要全局污染。因?yàn)镴S只有全局作用域和函數(shù)作用域(這話并不完全對(duì),但先記住,這就是JS讓人FUCK的原因。。。,不像JAVA,非常規(guī)矩,讓學(xué)的人,學(xué)起來也能非常清楚,省力)


3. who

JS有的,我們這里只討論JS的范疇,宿主環(huán)境,JS的引擎。其他語言,有的有,有的沒有



4.where

框架中,還有立即執(zhí)行函數(shù)中,JQUERY庫,JQ寫的小組件


5. when

看下面鏈接的文章



6. how1

具體用時(shí),要寫什么,先上一個(gè)小例子

例子:

var result = foo(1)(2); alert(result); function foo(a){return function(b){return a+b;} } 復(fù)制代碼

很簡(jiǎn)單,結(jié)果為3

再上一個(gè)有應(yīng)用場(chǎng)景的小例子

<html> <title>小例子</title> <meta http-equiv="Content-Type" content="text/html" ; charset="utf-8"> <body onload="myEffect()"> <table id="mytab" border="1"><tr><td>第0行</td></tr><tr><td>第1行</td></tr><tr><td>第2行</td></tr> </table> <div id="console" style="background:#ffff00"></div> </body> <script>function myEffect(){var console=document.getElementById('console');var tab=document.getElementById('mytab');var trs=tab.getElementsByTagName('tr');for(var i=0;i<trs.length;i++){trs[i].onclick=(function(){var rowNum=i;return function(){console.innerHTML="點(diǎn)擊了第"+rowNum+"行";}})();}} </script> </html> 復(fù)制代碼

試試,不去用 var rowNum=i;

而是改為:

trs[i].onclick=(function(){return function(){console.innerHTML="點(diǎn)擊了第"++"行";}})(); 復(fù)制代碼

會(huì)發(fā)生神馬,然后自行體會(huì)一下,再往下看

7.how2

實(shí)現(xiàn)原理

函數(shù)調(diào)用是用棧,存變量是用堆(不一定正確,只是比喻,為了方便理解),

函數(shù)被調(diào)用時(shí),函數(shù)

與內(nèi)存GC機(jī)制相關(guān),所以3時(shí)說,閉包,在其他語言中,有的有,有的沒有


一般來說,一個(gè)函數(shù)在執(zhí)行開始的時(shí)候,會(huì)給其中定義的變量劃分內(nèi)存空間保存,以備后面的語句所用,等到函數(shù)執(zhí)行完畢返回了,這些變量就被認(rèn)為是無用的了.對(duì)應(yīng)的內(nèi)存空間也就被回收了.下次再執(zhí)行此函數(shù)的時(shí)候,所有的變量又回到最初的狀態(tài),重新賦值使用.

但是如果這個(gè)函數(shù)內(nèi)部又嵌套了另一個(gè)函數(shù),而這個(gè)函數(shù)是有可能在外部被調(diào)用到的.并且這個(gè)內(nèi)部函數(shù)又使用了外部函數(shù)的某些變量的話.這種內(nèi)存回收機(jī)制就會(huì)出現(xiàn)問題.如果在外部函數(shù)返回后,又直接調(diào)用了內(nèi)部函數(shù),那么內(nèi)部函數(shù)就無法讀取到他所需要的外部函數(shù)中變量的值了.所以js解釋器在遇到函數(shù)定義的時(shí)候,會(huì)自動(dòng)把函數(shù)和他可能使用的變量(包括本地變量和父級(jí)和祖先級(jí)函數(shù)的變量(自由變量))一起保存起來.也就是構(gòu)建一個(gè)閉包,這些變量將不會(huì)被內(nèi)存回收器所回收,只有當(dāng)內(nèi)部的函數(shù)不可能被調(diào)用以后(例如被刪除了,或者沒有了指針),才會(huì)銷毀這個(gè)閉包,而沒有任何一個(gè)閉包引用的變量才會(huì)被下一次內(nèi)存回收啟動(dòng)時(shí)所回收.


這一段,即是原理,也是實(shí)現(xiàn),(更是核心關(guān)鍵,理解了這個(gè),就理解了閉包。)


用大白話,第一人稱的說話法是,我函數(shù)是大爺,我函數(shù)在定義時(shí),所用的變量,你必須都給我找地方存好了,就存一份就行,爺兒我被調(diào)用的時(shí)候,就要用這些變量!記做:你大爺永遠(yuǎn)是你大爺!補(bǔ)充:存的并不是這個(gè)變量聲明之時(shí)的快照,而是這些變量,在閉包函數(shù)執(zhí)行時(shí),變量中所存的真實(shí)值


函數(shù)的參數(shù),在這個(gè)函數(shù)每次被調(diào)用之時(shí),參數(shù)也是開出一個(gè)內(nèi)存空間去存的


看個(gè)TIME的例子,也是核心例子了!

for(var i = 0; i < 5; i++) {setTimeout(function() {console.log(i);}, 1); //1毫秒后,打印} 復(fù)制代碼

這個(gè)代碼,本意是想 打印

0

1

2

3

4

但是,打出來是

5

5

5

5

5

當(dāng)你知道“你大爺永遠(yuǎn)是你大爺”的理論后,就會(huì)明白,

function() {console.log(i); } 復(fù)制代碼

此函數(shù),所用的i這個(gè)變量,是存了一份,找地方放好了,但是這個(gè)變量i,他的值卻也在變化,所以當(dāng)此函數(shù)用這個(gè)變量時(shí),這個(gè)變量的值,就變?yōu)?#xff15;了!

要想達(dá)到輸出,0到4的結(jié)果,就要讓變量存上一份,并且沒有其他程序去改變他,就OK了

下面,提供四個(gè)改法,都是用了上面的理論,大家再體會(huì)一下

for(var i = 0; i < 5; i++) {setTimeout((function(ii) {return function(){console.log(ii);}})(i), 1);} 復(fù)制代碼

這是setTimeout內(nèi)部的函數(shù),去閉包存一份不變的變量法,還可以不用參數(shù)去存一份單獨(dú)的變量

for(var i = 0; i < 5; i++) {setTimeout((function() {var ii = i;return function(){console.log(ii);}})(), 1);} 復(fù)制代碼

我們?cè)賮?#xff0c;把單存的變量,放到setTimeout之外

for(var i = 0; i < 5; i++) {(function(ii) {setTimeout(function () {console.log(ii);}, 1);})(i);} 復(fù)制代碼

同理,也可以不用參數(shù):

for(var i = 0; i < 5; i++) {(function() {var ii = i;setTimeout(function () {console.log(ii);}, 1);})();} 復(fù)制代碼

這就是四個(gè)例子,核心思想就是讓閉包的變量是單獨(dú)的,不要被別的代碼去改變值,這樣就能達(dá)到想要的目的了,其實(shí)就是在內(nèi)存中建了5個(gè)變量,去存這0,1,2,3,4這5個(gè)變量的值,在需要的時(shí)候,取出來用。


8.tip

優(yōu)點(diǎn):

1.保護(hù)函數(shù)內(nèi)的變量安全,加強(qiáng)了封裝性

2.在內(nèi)存中維持一個(gè)變量(用的太多就變成了缺點(diǎn),占內(nèi)存)


缺點(diǎn)

閉包的缺點(diǎn)就是常駐內(nèi)存,會(huì)增大內(nèi)存使用量,內(nèi)存浪費(fèi),使用不當(dāng)很容易造成內(nèi)存泄露,無效內(nèi)存的產(chǎn)生


9.scene

為了看 復(fù)雜的代碼時(shí)用,自己主動(dòng)用得少,

藏于框架之中的有,交互響應(yīng),寫的函數(shù)中,傳的參數(shù)常量,就是閉包,但一般人就當(dāng)黑盒子看,對(duì)使用框架的人來說,是透明的

id.onclick = function(){ alert(i); } 循環(huán)四次,打出來,都是4

用閉包,就搞定了


前端開發(fā)必須知道的JS(二) 閉包及應(yīng)用

www.cnblogs.com/ljchow/arch…


PS : 沸水理論,簡(jiǎn)版,一壺水,只有燒到100度才能去喝,你每次都只燒到80度就不燒了,那么你永遠(yuǎn)也喝不上這水,學(xué)習(xí)也是一樣,快要學(xué)透閉包了,就停下來不學(xué),那么永遠(yuǎn)也不可能真正撐握閉包,不可能在工作中,隨心所欲的去使用閉包。


學(xué)到此,你應(yīng)該已經(jīng)是沸水100度了!


寫的不好,請(qǐng)大家多批評(píng):)


總結(jié)

以上是生活随笔為你收集整理的javascript闭包,你大爷永远是你大爷的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。