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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript:从此不再怕闭包

發布時間:2025/3/19 javascript 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript:从此不再怕闭包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

閉包就好像從JavaScript中分離出來的一個充滿神秘色彩的未開化世界,只有最勇敢的人才能到達那里。——《你不知道的JavaScript 上卷》

1、起源

js閉包很長一段時間里都是讓我頭疼的一個東西。工作中遇到類似這樣的代碼就很怕:

需求

頁面內三個按鈕,點擊按鈕控制臺輸出按鈕在所有按鈕中的序號,序號從1開始

說明

當然,實際的應用中我們一般不會有這么單純的需求,也不會寫這么刻意的代碼,這里我們為了學習,強行挖個坑,自己再填坑。

上代碼

<!DOCTYPE html> <html> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>閉包</title> </head> <body>點擊顯示按鈕序號<br><button>click</button><button>click</button><button>click</button><script>var btns = document.querySelectorAll("button");for(var i=0;i<btns.length;i++){btns[i].onclick = function(){console.log(i+1);}}</script> </body> </html> 復制代碼

不懂閉包前,我就覺得,這很優雅啊,按鈕在集合btns中的索引+1正好就是滿足需求的。興奮地趕緊自測,咔咔咔連點三下。

結果

當時內心表情大概就像上面這個哥們。但還是在工位上故作鎮定地趕緊百度了下。

修正

百度和修改后的for循環就變成了這個樣子,用一個閉包存一下數組索引i的值傳給閉包內的函數。

for(var i=0;i<btns.length;i++){btns[i].onclick = (function(tmpI){return function(){console.log(tmpI+1);} })(i); } 復制代碼

click,click,click。大功告成!

2、原理

工作中滿足了當時的需求也就立馬沉迷代碼擼下一個功能去了。但對閉包的詳細原理知之甚少,相關問題稍微發生點變化,就又可能讓自己云里霧里。近來專門找了幾本書,刻意攻克了下,才算開始了解了閉包。

如上問題的解析

代碼再貼一下:

var btns = document.querySelectorAll("button"); for(var i=0;i<btns.length;i++){btns[i].onclick = function(){console.log(i+1);} } 復制代碼

上面代碼不能按需實現功能的問題在于: 1、for循環內只是將匿名函數引用賦給onclick方法,在函數被調用時才會去實時取i的值 2、i為全局變量,在onclick方法觸發時,i的值已被i++的操作變成了4

for(var i=0;i<btns.length;i++){btns[i].onclick = (function(tmpI){return function(){console.log(tmpI+1);} })(i); } 復制代碼

上述代碼,onclick方法獲得的匿名函數通過立即執行函數返回,立即執行函數內又通過傳參的方式,將i的值傳入,用tmpI變量保存起來。確保了外部的i++操作不會影響函數內的tmpI的值的變化,就解決了問題。

閉包定義

"閉包(closure)是一個函數在創建時允許自身函數訪問并操作該自身函數之外的變量時所創建的作用域。"——《JavaScript 忍者秘籍》

這是我覺得相對來說比較易懂的對閉包的解釋。關鍵要素有兩個: 1、函數創建時產生。 2、允許自身訪問并操作函數之外的變量。 上述代碼return的匿名函數中訪問了其函數之外的tmpI變量,形成了閉包。

按書中定義,如下我們大家每天都在寫的代碼也屬于閉包。

var outerValue = "外部變量";function outerFunction(){console.log("outerValue",outerValue); } outerFunction(); 復制代碼

按定義,outerFunction確實訪問了其外的outerValue值,屬于閉包。但因為函數定義和外部變量都處在全局作用域中,該作用域從未消失過,所以我們也沒覺得這有什么特殊的地方。通過實際的chrome調試發現,chrome也不會標記此類的閉包。以下,我們和chrome保持一致,不再特別說明全局作用域閉包。

再舉個栗子

var outerValue ="外部變量"; var later;function outerFunction(){var innerValue = "內部值";function innerFunction(paramValue){console.log(outerValue,"Inner can see the outerValue.");console.log(innerValue,"Inner can see the innerValue.");console.log(paramValue,"Inner can see the paramValue.");console.log(tooLate,"Inner can see the tooLate.");}later = innerFunction; }console.log(tooLate,"Outer can't see the tooLate."); var tooLate = "outerFunction之后聲明的變量";outerFunction(); later("later參數"); 復制代碼

輸出結果如下:

上述例子引用自《JavaScript 忍者秘籍》,筆者做了部分修改。這里innerFunction函數創建時形成了閉包,其訪問了outerFunction中的innerValue。 其余部分的代碼書中是為了說明閉包的三種更有趣的性質。
1、內部函數的參數是包含在閉包中的。(這是顯而易見的)
2、作用域之外的所有變量,即便是函數聲明之后的那些聲明,也都包含在閉包中。(在調用later時可以訪問到tooLate變量)
3、相同的作用域內,尚未聲明的變量不能進行提前引用。(如代碼中先打印的tooLate為undefined,我覺得這也是顯而易見的。)

chrome中對outerFunction閉包的標識如下:

在調用outerFunction,定義innerFunction時,訪問了innerValue,形成了outerFunction閉包。

3、延伸

按我的理解,js有閉包的概念是因為js設計之初沒有塊級作用域,只能通過函數來限制變量的有效范圍。當有了塊級作用域,其實也就不再需要寫閉包。如開頭例子如果用ES6 let改寫,也可實現需求功能。

var btns = document.querySelectorAll("button"); for(let i=0;i<btns.length;i++){btns[i].onclick = function(){console.log(i+1);} } 復制代碼

讀者可以試下,這也是滿足需求的。這是因為使用let定義i,ES6做了處理,每次循環的i都有各自的作用域,其值不會互相影響,函數調用時,其仍然保持了原值。

文中內容有錯誤,或讀者對此仍有疑惑的,歡迎大家在評論中留言或者加微信一起探討學習。

主要參考資料

《你不知道的JavaScript 上卷》——[美]Kyle Simpson
《JavaScript 忍者秘籍》——[美]John Resig,Bear Bibeault

轉載于:https://juejin.im/post/5ce12c285188254081056efa

總結

以上是生活随笔為你收集整理的JavaScript:从此不再怕闭包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 禁断介护av一区二区 | 秋霞毛片 | 全部免费毛片在线播放一个 | 亚洲一二三四视频 | 国产人人干 | 丰满少妇久久久久久久 | 亚洲精品字幕 | 三级少妇 | 日日网| 在线视频a | 亚洲砖区区免费 | 国内精品亚洲 | 91视频这里只有精品 | 国产伦精品一区二区三区视频免费 | 加勒比久久综合 | 国产www精品 | 欧美亚洲一区二区三区 | 欧美三日本三级少妇99 | 校花被c到呻吟求饶 | 成人欧美在线视频 | www.五月婷 | 国产人妖网站 | 日日骚影院| 亚洲五月婷 | 九一在线视频 | 桃色激情网| 中文字幕有码在线观看 | 丰满少妇av | 一道本在线 | 国产伦精品 | 国产91免费视频 | 欧美成人手机在线视频 | 日本a级c片免费看三区 | 伊人影院99| 天天射天天搞 | 无码国产色欲xxxxx视频 | 日本做爰三级床戏 | 国产女同91疯狂高潮互磨 | 日韩在线视频中文字幕 | 亚洲av综合色区无码二区爱av | 国产人妻黑人一区二区三区 | 91精品人妻一区二区 | 亚洲国产精品成人 | 国产在线拍揄自揄拍无码视频 | 成人国产免费观看 | 17c国产精品一区二区 | 国产精品视频合集 | 在线观看一区二区三区四区 | 天天谢天天干 | 黄色国产一级片 | 欧美日韩中文字幕在线视频 | 天天射天天爽 | 一级做a爰片毛片 | 免费草逼网站 | 亚洲av午夜精品一区二区三区 | 国产又粗又猛又爽又黄av | 97人妻精品一区二区三区动漫 | 一级免费大片 | 日韩一区欧美一区 | 久久久久久久久久久网站 | www精品国产 | 精品久久久久久亚洲精品 | 亚洲一区二区三区在线 | 精品一二区| 人人干天天干 | 韩国一二三区 | 人人做人人爽人人爱 | 在线观看毛片网站 | 色综合天天 | 白白色免费视频 | 国产第三页 | 香蕉依人 | 欧美高清免费 | 国产在线播放一区 | 国产夫妻在线视频 | 亚洲AV成人午夜无码精品久久 | 最新日本中文字幕 | 青娱乐在线视频免费观看 | a猛片免费播放 | 天天摸天天摸 | 国产成人无码性教育视频 | 人人妻人人澡人人爽精品欧美一区 | 一区二区三区四区精品视频 | 成人免费毛片嘿嘿连载视频 | 国产福利视频一区二区三区 | 可以在线看黄的网站 | 色七七桃花综合影院 | 真人一及毛片 | 无码人妻精品一区二区 | 欧美sm凌虐视频网站 | 成人看的毛片 | 亚洲视频在线免费播放 | 香蕉久久久久久久av网站 | 国产女主播喷水高潮网红在线 | 午夜欧美精品久久久久久久 | 欧美激情在线狂野欧美精品 | 手机在线观看免费av | 日韩免费av在线 | 外国电影免费观看高清完整版 |