JS閉包經(jīng)典實(shí)例詳解
本文實(shí)例講述了JS閉包。分享給大家供大家參考,具體如下:
之前花了很多時(shí)間看書上對(duì)閉包的介紹,也看了很多人的寫的關(guān)于閉包的博客,然后我就以為自己懂了。
結(jié)果,下午在一個(gè)QQ群里,有人問了這道經(jīng)典的閉包問題,如下圖:
我告訴他去看書上的閉包介紹。告訴他之后,我想我自己要不也寫一下,反正花不了多少時(shí)間,結(jié)果花了好久怎么寫也不對(duì)..............
后來(lái)看了看書上的,然后自己總結(jié)了下,覺得這次應(yīng)該懂了。下次還不理解我就可以去跳樓了............
-----------------------------------分割線-----------------------------------分割線--------------------------
首先我們來(lái)了解幾個(gè)概念:
立即執(zhí)行函數(shù):形如 (function(){})();
的一類函數(shù);
閉包:閉包是指有權(quán)訪問另一函數(shù)作用域中的變量的函數(shù)。
作用域鏈:當(dāng)代碼執(zhí)行的時(shí)候,會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈....(具體百度)
我們?cè)賮?lái)看這個(gè)問題,我重新寫了一個(gè),源碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>閉包經(jīng)典例子詳解——huansky</title> </head> <body> <div id="ttt"> <p >000000000000000000</p> <br> <p >111111111111111111</p> <br> <p >222222222222222222</p> </div> </body> <script> var dom=document.getElementsByTagName("p"); for(var i=0;i<dom.length;i++){ dom[i].onclick=function(){ console.log(i);//3 }; } </script> </html>
首先,代碼中的匿名函數(shù)沒有變量 i,所以它必須向上查找,在全局環(huán)境中找到了 i。
當(dāng)for
循環(huán)運(yùn)行后,全局變量中的 i 變成了3。此時(shí)當(dāng)你點(diǎn)擊文字的時(shí)候,會(huì)調(diào)用其綁定的函數(shù),而該函數(shù)運(yùn)行的時(shí)候,發(fā)現(xiàn)自己沒有 i,就會(huì)取得全局環(huán)境中的 i。
所以,最后的結(jié)果是,不管你點(diǎn)擊那段文字,最后結(jié)果都是3。
PS:感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼,看看運(yùn)行效果。
那怎么辦呢?你可以用立即執(zhí)行函數(shù),看代碼:
for(var i=0;i<dom.length;i++){ dom[i].onclick=function(i){ return function( ){ console.log(i); }; }(i); }
我們把參數(shù) i 作為傳給立即執(zhí)行函數(shù),這樣,i 的值就傳給了立即執(zhí)行函數(shù)的局部變量 i 了。立即執(zhí)行函數(shù)會(huì)直接執(zhí)行,但是其活動(dòng)不會(huì)銷毀,因?yàn)槔锩嬗袀€(gè)匿名函數(shù)。執(zhí)行后局部變量 i 與全局變量 i 聯(lián)系就切斷了,也就是執(zhí)行的時(shí)候,傳進(jìn)去的變量 i 是多少,立即執(zhí)行函數(shù)的局部變量 i 就是多少,并且該局部變量 i 仍然沒有消失,因?yàn)槟涿瘮?shù)的存在。
這時(shí)候,return
中的匿名函數(shù)的作用域鏈中會(huì)有兩個(gè)變量 i。當(dāng)點(diǎn)擊文本的時(shí)候,它向上搜索 i 的時(shí)候,它找到立即執(zhí)行函數(shù)的局部變量 i ,就停止向上查找了,因此最后的結(jié)果就不會(huì)是全局變量 i 的值3了。
有一個(gè)方法可以檢驗(yàn)?zāi)銈冇袥]有真的理解上面所說(shuō)的,看上面的變體,代碼:
for(var i=0;i<dom.length;i++){ dom[i].onclick=function(t){ return function( ){ console.log(t);//1 console.log(i);//3 }; }(i); }
其實(shí)return中的匿名函數(shù)中的 t 就是立即執(zhí)行函數(shù)的局部變量 i,而 i 就是 指全局變量 i,因?yàn)榱⒓磮?zhí)行函數(shù)中沒有變量i,只能繼續(xù)向上搜索,然后就找到全局變量的 i 了。
如果看到這里,你還沒有理解,有兩個(gè)原因:一個(gè)原因是我表達(dá)的不夠好,另一個(gè)原因是你沒有完全理解前面提到的這些概念,還要繼續(xù)看書。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
JS實(shí)現(xiàn)數(shù)組過(guò)濾從簡(jiǎn)單到多條件篩選
一般情況下的單條件篩選,數(shù)組的filter方法就能夠滿足需求,本文討論的重點(diǎn)是多條件下的復(fù)合篩選,并列出了幾個(gè)相關(guān)知識(shí)點(diǎn),感興趣的可以了解一下2021-07-07微信小程序?qū)崿F(xiàn)人臉識(shí)別登陸的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)人臉識(shí)別登陸的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04基于javascript的無(wú)縫滾動(dòng)動(dòng)畫1
這篇文章主要介紹了基于javascript的無(wú)縫滾動(dòng)動(dòng)畫實(shí)現(xiàn),文章通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08微信小程序上傳圖片并等比列壓縮到指定大小的實(shí)例代碼
這篇文章主要介紹了微信小程序 上傳圖片并等比列壓縮到指定大小,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10JavaScript實(shí)現(xiàn)正則去除a標(biāo)簽并保留內(nèi)容的方法【測(cè)試可用】
這篇文章主要介紹了JavaScript實(shí)現(xiàn)正則去除a標(biāo)簽并保留內(nèi)容的方法,結(jié)合實(shí)例形式詳細(xì)分析了javascript針對(duì)a標(biāo)簽及span標(biāo)簽的正則匹配相關(guān)操作技巧,需要的朋友可以參考下2018-07-07javascript顯示動(dòng)態(tài)時(shí)間的方法匯總
本文給大家匯總介紹了3種javascript實(shí)現(xiàn)動(dòng)態(tài)顯示時(shí)間的方法及詳細(xì)示例,有需要的小伙伴可以參考下2018-07-07