精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

重學JavaScript(函數)閉包

開發 后端
JavaScript函數內部可以讀取函數外部的變,但反過來,函數的外部通常則無法讀取函數內部的變量。在實際應用中,有時需要真正在函數外部訪問函數內部的局部變量,此時最常用的方法就是使用閉包。

 前言
我們知道,作用域鏈查找標識符的順序是從當前作用域開始一級一級往上查找。因此,通過作用域鏈,JavaScript函數內部可以讀取函數外部的變,但反過來,函數的外部通常則無法讀取函數內部的變量。在實際應用中,有時需要真正在函數外部訪問函數內部的局部變量,此時最常用的方法就是使用閉包。

那么什么是閉包?所謂閉包,就是同時含有對函數對象以及作用域對象引用的對象。閉包主要是用來獲取作用域鏈或原型鏈上的變量或值。創建閉包最常見的方式是在一個函數中聲明內部函數(也稱嵌套函數),并返回內部函數。此時在函數外部就可以通過調用函數得到內部函數。雖然按照閉包的概念,所有訪問了外部變量的JavaScript函數都是閉包。但我們平常絕大部分時候所謂的閉包其實指的就是內部函數閉包。
閉包可以將一些數據封裝私有屬性以確保這些變量的安全訪問,這個功能給應用帶來了極大的好處。需要注意的是,閉包如果使用不當,也會帶來一些意想不到的問題。下面就通過幾個示例來演示一下閉包的創建、使用和可能存在的問題及其解決方法。
示例1: 創建閉包。

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4.  <title>閉包</title> 
  5. </head> 
  6. <body> 
  7. <script type="text/javascript"
  8.  function outer(argument) { 
  9.   var b=0; 
  10.   return function inner (){ 
  11.    b++; 
  12.    console.log("內部的b:"+b); 
  13.   } 
  14.  } 
  15.  var func =  outer();//1 通過外部變量引用函數返回的內部函數 
  16.  console.log(func);//2 輸出內部函數定義代碼 
  17.  func();//3 通過閉包訪問局部變量b,此時b=1; 
  18.  console.log("外部函數中b:"+b); //4 出錯,報引用錯誤。 
  19. </script> 
  20. </body> 
  21. </html> 

上述代碼在外部函數outer中聲明內部函數inner,并返回內部函數,同時在outer函數外面,變量func引用了outer函數返回的內部函數,所以內部函數inner是一個閉包。該閉包訪問了外部函數的局部變量b。1處代碼通過調用外部函數返回內部函數并賦給外部變量func,使func變量引用內部函數,所以2處代碼將輸出inner函數的整個定義代碼。3處代碼通過對外部變量func添加一對小括號后調用內部函數inner,從而達到在函數外部訪問局部變量b的目的。執行4處的代碼時將報ReferenceError錯誤,因為b是局部變量,不能在函數外部直接訪問局部變量。
我們知道函數執行完畢時,運行期上下文會被銷毀,與之關聯的活動對象也會隨之銷毀,因此離開函數后,屬于活動對象的局部變量將不能被訪問。但是為什么上述示例中的outer函數執行完后,它的局部變量還能被內部函數訪問呢?這個問題我們可以用作用域鏈來解釋。
當執行1處代碼調用outer函數時,JavaScript引擎會創建outer函數執行上下文的作用域鏈,這個作用域鏈包含了outer函數執行時的活動對象,同時JavaScript引擎也會創建一個閉包,而閉包因為需要訪問outer函數的局部變量,因而其作用鏈也會引用outer的活動對象。這樣,當outer函數執行完后,它的作用域對象因為有閉包的引用而依然存在,固而可以提供給閉包訪問。
上述示例中的內部函數雖然有名稱,但在調用是并沒有用到這個名稱,所以內部函數的名稱可以缺省,即可以將內部函數修改為匿名函數,從而簡化代碼。
示例2: 經典閉包問題

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4. <title>經典閉包問題</title> 
  5. <script type="text/javascript"
  6.  window.onload=function () { 
  7.   var abtn = document.getElementsByTagName("button"); 
  8.   for (var i = 0; i<abtn.length; i++) { 
  9.    abtn[i].onclick=function(){ 
  10.     alert("按鈕"+(i+1)); 
  11.    } 
  12.   } 
  13.  } 
  14. </script> 
  15. </head> 
  16. <body> 
  17. <button>按鈕1</button> 
  18. <button>按鈕2</button> 
  19. <button>按鈕3</button> 
  20. </body> 
  21. </html> 

該示例期望實現的功能是,單擊每個按鈕時,在彈出的警告對話框中顯示相應的標簽內容,即單擊3個按鈕時將分別顯示“按鈕1”、“按鈕2”、“按鈕3”。
上述示例頁面加載完后觸發窗口加載事件,從而執行外層匿名函數,外層匿名函數執行完循環語句后使活動對象中的局部變量i的值修改為3。外層匿名函數執行完后撤銷,但由于其活動對象中的abtn和i變量被內層匿名函數引用,因而外層匿名函數的活動對象仍然存在堆中供內層匿名函數訪問。每執行一次循環都將創建一個閉包,這些閉包都引用了外層匿名函數的活動對象,因而訪問變量i時都得到3,這樣最后的結果是單擊每個按鈕,在警告對話框中顯示的文字都是“按鈕4” (i+1=3+1),與期望的功能不一致。造成這個問題的原因是,每個閉包都引用一個變量,如果我們使不同的閉包引用不同的變量,就可以實現輸出的結果不一樣。這個需求可使用多種方法實現,在此介紹使用立即調用函數表達式(IIFE)和ES6中的let創建塊即變量的方法。
IIFE指的是:在定義函數的時候直接執行,即此時函數定義變成了一個函數調用的語句。要讓一個函數定義語句變成函數調用語句,就需要將定義語句變為一個函數表達式,然后在該表達式后面再加一對圓括號()即可。將函數定義語句變為一個函數表達式的最常用方法就是將整個定義語句放在一對圓括號中。
1、IIFE中的函數為一個匿名函數

  1. (function(name){ 
  2.  console.log("hello,"+name); 
  3. })("maomin"); 

JS引擎執行上述代碼時,會調用匿名,同時將后面圓括號中的參數maomin傳給name虛參,結果得到:"hello,maomin"。
2、IIFE中的函數為一個有名函數

  1. (function func (name) { 
  2.  console.log("I am"+name); 
  3. })("maomin"

上述代碼跟匿名函數完全一樣。

示例3: 使用立即調用函數表達式解決經典閉包問題

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4.  <title>使用立即調用表達式解決經典閉包問題</title> 
  5.  <script type="text/javascript"
  6.  window.onload=function () { 
  7.   var abtn = document.getElementsByTagName("button"); 
  8.   for (var i = 0; i<abtn.length; i++) { 
  9.    (function(num){ 
  10.     abtn[num].onclick=function(){ 
  11.         alert("按鈕"+(num+1)); 
  12.        } 
  13.    })(i) 
  14.   } 
  15.  } 
  16. </script> 
  17. </head> 
  18. <body> 
  19. <button>按鈕1</button> 
  20. <button>按鈕2</button> 
  21. <button>按鈕3</button> 
  22. </body> 
  23. </html> 

上述代碼中第二個匿名函數為IIFE,每次調用該匿名函數時將生成一個對應該函數的活動對象。該對象中包含可一個函數參數,值為當次循環的循環變量值。上述示例中,IIFE共執行了3次,因而共生成了3個活動對象,活動對象中包含的參數值分別為0、1和2,依次對應IIFE的3次執行。
每次執行IIFE時,將會產生一個閉包,該閉包會引用對應按鈕索引順序執行IIFE的活動對象,而閉包引用的活動對象中的參數值剛好等于按鈕的索引值,因而單擊3個按鈕將在彈出的警告框中分別顯示"按鈕1"、“按鈕2”、“按鈕3”。
示例4:使用ES6中的let關鍵字創建塊級變量解決經典閉包問題

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4.  <title>使用ES6中的let關鍵字解決經典閉包問題</title> 
  5.  <script type="text/javascript"
  6.  window.onload=function () { 
  7.   var abtn = document.getElementsByTagName("button"); 
  8.   for (let i = 0; i<abtn.length; i++) { 
  9.    abtn[i].onclick=function(){ 
  10.     alert("按鈕"+(i+1)); 
  11.    } 
  12.   } 
  13.  } 
  14. </script> 
  15. </head> 
  16. <body> 
  17. <button>按鈕1</button> 
  18. <button>按鈕2</button> 
  19. <button>按鈕3</button> 
  20. </body> 
  21. </html> 

上述代碼中循環變量使用let聲明,因而每次循環時,都會產生一個新的塊級變量,所以在頁面加載完,執行外層匿名函數時產生的活動對象中包含了3個對應循環變量的塊級變量,變量值分為0、1和2。每執行一次循環,將會產生一個閉包,該閉包中的變量i會引用外層匿名函數的活動對象對應按鈕索引的塊級變量,因而單擊3個按鈕時將在彈出的警告對話框中分別顯示“按鈕1”、“按鈕2”、“按鈕3”。

責任編輯:姜華 來源: 前端歷劫之路
相關推薦

2021-02-21 16:21:19

JavaScript閉包前端

2011-05-25 14:48:33

Javascript閉包

2021-01-22 07:48:07

JavaScript 高階函數閉包

2016-09-14 09:20:05

JavaScript閉包Web

2009-07-24 17:30:37

Javascript閉

2017-09-14 13:55:57

JavaScript

2021-05-21 09:01:29

JavaScript 前端函數閉包

2016-09-18 20:53:16

JavaScript閉包前端

2017-05-22 16:08:30

前端開發javascript閉包

2009-03-17 15:36:29

JavaScript循環事件

2021-01-13 11:25:12

JavaScript閉包函數

2010-06-23 10:24:42

Javascript閉

2012-11-29 10:09:23

Javascript閉包

2011-05-12 18:26:08

Javascript作用域

2011-05-30 14:41:09

Javascript閉

2011-03-02 12:33:00

JavaScript

2024-01-22 09:51:32

Swift閉包表達式尾隨閉包

2021-12-06 07:15:48

Javascript作用域閉包

2023-07-11 08:46:38

閉包函數Rust

2023-02-07 07:47:52

Python裝飾器函數
點贊
收藏

51CTO技術棧公眾號

老牛影视av牛牛影视av| 欧美日韩中文字幕在线观看| 午夜欧美巨大性欧美巨大 | 国产精品久久综合av爱欲tv| 久久久国产一级片| 成人激情自拍| 欧美性一级生活| 97久久国产亚洲精品超碰热| 青青久草在线| 国产毛片精品国产一区二区三区| 97精品视频在线| 美女视频久久久| 日韩高清影视在线观看| 91精品久久久久久蜜臀| 91九色在线观看视频| 在线观看h片| 成人精品小蝌蚪| 国产免费一区视频观看免费| 99热国产在线观看| 国产精品麻豆久久| 亚洲天堂av在线免费| 伦伦影院午夜理论片| 免费观看成人性生生活片| 亚洲综合久久av| 杨幂一区欧美专区| 韩国福利在线| 在线免费观看av的网站| 91精品国产综合久久蜜臀| 国产不卡精品视男人的天堂| 波多野结衣在线网址| 日韩激情网站| 日韩免费高清av| 中文字幕第17页| 日本高清不卡一区二区三区视频 | 鲁丝一区鲁丝二区鲁丝三区| 99精品在线视频观看| 蜜桃在线一区二区三区| 欧美最猛黑人xxxx黑人猛叫黄| 九九热国产在线| 午夜精品毛片| 日韩在线视频网站| xxxx日本黄色| 黄色一级大片在线免费看国产| 日韩综合一区二区| 欧美在线视频网| 久久久久久久九九九九| 91精品观看| 欧美日韩亚洲一区二区三区| 久久久久久**毛片大全| 国产做受高潮69| 国产一区二区播放| 国产精品伦理久久久久久| 中文字幕综合在线| 欧美激情视频二区| 成人羞羞网站入口免费| 国产一区二区三区视频免费| 日韩av在线看免费观看| 特黄特色欧美大片| 亚洲女人天堂色在线7777| 性久久久久久久久久| 亚洲国产欧美日韩在线观看第一区 | 亚洲精品网址在线观看| 少妇精品一区二区| 香蕉久久夜色精品国产更新时间 | 91超碰在线免费观看| 国产女人高潮毛片| 国产成人自拍网| 国产高清在线精品一区二区三区| 亚洲精品字幕在线| av一区二区三区四区| 精品国产欧美一区二区三区成人| 男人天堂资源网| 国产国产精品| 久久99久久99精品中文字幕| 国产午夜福利一区二区| 国产精品日韩| 国产精品一区二区在线| 国产精品久久综合青草亚洲AV| 国产一区二区三区观看| 国产精品一区二区欧美| 青青草视频在线观看| 久久精品视频在线免费观看| 一区二区在线观| 四虎av在线| 欧美日韩另类字幕中文| 日韩精品视频一二三| 久久视频社区| 精品亚洲男同gayvideo网站| 日本在线观看网址| 日韩一级不卡| 国产久一一精品| 乱精品一区字幕二区| 国产喷白浆一区二区三区| 超碰10000| 欧美日韩国产v| 欧美一级午夜免费电影| 国产精品三级在线观看无码| 热久久天天拍国产| 久久久久久中文字幕| 欧美一区二区三区网站| 国产一区二区伦理片| 麻豆亚洲一区| 午夜伦理在线视频| 在线观看亚洲一区| 国产大尺度视频| 日韩欧美高清| 91av在线精品| 精品人妻少妇嫩草av无码专区| 久久久久久久久蜜桃| 免费cad大片在线观看| 性高爱久久久久久久久| 欧美成人在线直播| 日韩免费av一区| 老鸭窝亚洲一区二区三区| 久久精品国产91精品亚洲| 久久国产精品波多野结衣| 视频一区视频二区中文| 国产一区二区三区高清视频| 欧洲不卡av| 色综合久久久网| 催眠调教后宫乱淫校园| 国产精品成久久久久| 国产成人短视频| 少妇高潮一区二区三区99小说| 亚洲欧洲精品成人久久奇米网| 国产精品丝袜久久久久久消防器材| 国产高清视频一区二区| 宅男66日本亚洲欧美视频| 欧美日韩综合在线观看| 国产精一区二区三区| 亚洲国产精品www| 亚洲精品88| 亚洲激情 国产| 免费在线观看黄色av| 国内一区二区在线| 亚洲欧美综合一区| 国产经典一区| 亚洲性视频网站| 99精品人妻国产毛片| 91丨九色丨蝌蚪丨老版| 国产深夜男女无套内射| 电影一区二区在线观看| 欧美丰满少妇xxxxx做受| 国产欧美一区二区三区视频在线观看| 国产精品麻豆视频| 三级a三级三级三级a十八发禁止| 国产欧美日韩在线观看视频| 日韩美女视频中文字幕| 美州a亚洲一视本频v色道| 精品欧美激情精品一区| 欧美成人三级伦在线观看| 日韩视频三区| 精品一区久久久| 亚洲v.com| 国产亚洲精品久久久| 欧美国产一级片| 精品人妻一区二区三区潮喷在线| 国产精品第十页| 国产高清自拍一区| free性欧美16hd| 成人性生交大片| 97视频免费在线看| 亚洲欧美色视频| 欧美视频专区一二在线观看| 中国黄色a级片| 日韩在线播放一区二区| 婷婷四房综合激情五月| 欧美啪啪网站| 欧美久久精品午夜青青大伊人| 亚洲av综合色区无码一区爱av| 一区二区三区鲁丝不卡| 五月天激情小说| 日韩av一区二| aaa免费在线观看| eeuss国产一区二区三区四区| 久久久在线免费观看| 久久久久久女乱国产| 欧美日韩一级黄| 欧美毛片在线观看| 久久久久久9999| 波多野结衣在线免费观看| 一本久久综合| 色一情一乱一伦一区二区三区| 99久久这里有精品| 97精品一区二区三区| 91网页在线观看| 日韩欧美资源站| 久久伊人成人网| 懂色av粉嫩av蜜臀av| 成人激情直播| 欧美一区视久久| 一道本在线观看视频| 欧美日韩大尺度| 国产又黄又粗又猛又爽的视频 | 日中文字幕在线| 亚洲国产aⅴ天堂久久| 四虎永久免费在线观看| 激情欧美日韩一区二区| 国产成人亚洲综合无码| 亚洲国产合集| 亚洲自拍偷拍色片视频| 欧美国产大片| 久精品免费视频| 国产精品一级伦理| 亚洲国产黄色片| 中国丰满人妻videoshd| 亚洲一区导航| 热久久99这里有精品| 成人video亚洲精品| 亚洲欧洲在线视频| 亚洲欧美强伦一区二区| 欧美欧美欧美欧美首页| 国产第100页| 日韩毛片高清在线播放| 丰满少妇在线观看资源站| 国产高清不卡二三区| 久草福利视频在线| 中日韩视频在线观看| 加勒比海盗1在线观看免费国语版| 欧美最新另类人妖| 久久久久久久久久久久久久久久av| 国产一区二区视频在线看| 国产精品视频资源| 亚洲v.com| 5566日本婷婷色中文字幕97| 黄色在线观看视频网站| 欧美老女人xx| 成人午夜在线影视| 深夜成人在线观看| 成人高潮成人免费观看| 亚洲欧美国产精品久久久久久久 | 亚洲国产欧美一区| 国产丰满美女做爰| 91精品国产一区二区三区香蕉| 亚洲免费视频二区| 欧美亚洲日本一区| 成人小视频在线播放| 日韩欧美国产成人| 日本熟女毛茸茸| 欧美性xxxxxx| 色阁综合av| 久久精品嫩草影院| 国产精品91久久久久久| 午夜影院在线观看国产主播| 91av国产在线| 亚洲性色av| 国产成人精品免高潮费视频| 欧美xx视频| 国产成人亚洲综合青青| 九九热线视频只有这里最精品| 日本精品视频在线观看| 欧美羞羞视频| 国产精品久久久久久久av电影| 日韩网站中文字幕| 国产精品日韩在线| 亚洲免费一区| 国产精品v欧美精品v日韩精品| 成人在线超碰| 精品免费视频123区| 国产成人高清| 一区二区不卡在线观看| 中文在线日韩| 成人网站免费观看入口| 亚洲免费婷婷| 日日噜噜噜噜久久久精品毛片| 麻豆精品新av中文字幕| 性鲍视频在线观看| caoporen国产精品视频| 扒开jk护士狂揉免费| 亚洲欧洲美洲综合色网| 欧美日韩综合一区二区| 精品久久久久久国产91| 日本黄色中文字幕| 欧美一三区三区四区免费在线看| 亚洲国产精品18久久久久久| 亚洲精品小视频在线观看| 91在线网址| 欧美激情视频一区二区| 天堂√中文最新版在线| 国产成人一区二| 亚洲精品国产九九九| 欧美一区国产一区| 欧美福利视频| 欧美a在线视频| 精一区二区三区| 少妇饥渴放荡91麻豆| 中文乱码免费一区二区| 欧美交换国产一区内射| 欧美性xxxxxxxxx| va视频在线观看| 亚洲欧美国内爽妇网| 国产精品一区二区三区视频网站| 91精品91久久久久久| 日韩一区二区三区四区五区 | 亚洲女性喷水在线观看一区| 日韩av在线天堂| 欧美人伦禁忌dvd放荡欲情| 色窝窝无码一区二区三区成人网站| 国产亚洲视频在线| 第四色日韩影片| 成人福利在线观看| 一区二区三区韩国免费中文网站| 中日韩在线视频| 久久综合网络一区二区| 韩国av中国字幕| 中文字幕一区在线观看| 精品久久久久久久久久久久久久久久| 欧美一区二区视频观看视频| 视频国产一区二区三区| 久久99国产精品自在自在app | 日本亚洲三级在线| 日本一卡二卡在线| 亚洲精品日韩综合观看成人91| 看黄色一级大片| 亚洲精品一区二区三区婷婷月| 丝袜在线观看| 亚洲精品免费在线视频| 日韩欧美高清在线播放| 国产精品第12页| 91欧美激情一区二区三区成人| 久久国产精品二区| 日韩欧美亚洲一区二区| 日本在线看片免费人成视1000| 日韩美女视频中文字幕| 日韩超碰人人爽人人做人人添| 日韩精品视频在线观看视频| 极品少妇xxxx精品少妇| 日韩av毛片在线观看| 91黄视频在线观看| 国产视频福利在线| 91成人在线视频| 亚洲精品国产精品粉嫩| 亚洲 自拍 另类小说综合图区| 国产精品一区二区久久不卡| 日本爱爱小视频| 欧美日韩国产首页在线观看| 91青青在线视频| 国产情人节一区| 色综合久久一区二区三区| 天天爽夜夜爽一区二区三区| 中文字幕av一区 二区| 中文在线观看免费高清| 中文字幕久精品免费视频| 国产综合av| 日韩欧美一区二区三区四区 | 91亚洲国产精品| 久久精品免费一区二区三区| 亚洲三级在线观看视频| 亚洲图片激情小说| av综合在线观看| 欧美高清不卡在线| 国产成人aa在线观看网站站| 久久国产精品网| 91亚洲国产成人精品一区二区三| 天天综合网久久综合网| 亚洲美女又黄又爽在线观看| 日韩久久一区二区三区| 亚洲视频精品一区| 九九九久久久精品| 久久精品国产亚洲AV无码麻豆 | 成人在线视频免费播放| 天天综合色天天综合| 欧美挠脚心网站| 国产精品网站大全| 中文乱码免费一区二区三区下载| 99久久久无码国产精品性波多| 亚洲狠狠爱一区二区三区| 香蕉视频国产在线| 国产成人a亚洲精品| 亚洲二区三区不卡| 在线精品视频播放| 色国产综合视频| 爆操欧美美女| 精品在线不卡| 久久精品99国产精品日本| 欧美特级一级片| 日韩大片免费观看视频播放| 超碰这里只有精品| 日韩在线视频在线| 久久人人超碰精品| 国产免费一区二区三区最新不卡| 国内精品久久久久久影视8| 国产日产精品_国产精品毛片| 天天干天天色天天干| 精品女同一区二区三区在线播放| av在线资源站| 国产精品日韩一区二区三区 | 欧美日韩美女在线| 免费在线观看av片| 女人一区二区三区| 国产一区中文字幕| 欧美videossex极品| 欧美成人免费一级人片100| 人妖一区二区三区| 久久精品亚洲天堂| 色综合天天视频在线观看 | 亚洲一区二区中文在线| 国产毛片在线| 国产一级精品aaaaa看| 精品综合免费视频观看|