js中的閉包

閉包是js的一個難點也是它的一個特色,是我們必須掌握的js高級特性,那么什么是閉包呢?它又有什么用呢?

我們都知道,js的作用域分兩種,全局局部,基于我們所熟悉的作用域鏈相關知識,我們知道在js作用域環(huán)境中訪問變量的權利是由內向外的,內部作用域可以獲得當前作用域下的變量并且可以獲得當前包含當前作用域的外層作用域下的變量,反之則不能,也就是說在外層作用域下無法獲取內層作用域下的變量,同樣在不同的函數(shù)作用域中也是不能相互訪問彼此變量的,那么我們想在一個函數(shù)內部也有限權訪問另一個函數(shù)內部的變量該怎么辦呢?閉包就是用來解決這一需求的,閉包的本質就是在一個函數(shù)內部創(chuàng)建另一個函數(shù)
我們首先知道閉包有3個特性:
①函數(shù)嵌套函數(shù)
②函數(shù)內部可以引用函數(shù)外部的參數(shù)和變量
③參數(shù)和變量不會被垃圾回收機制回收

本文我們以閉包兩種的主要形式來學習

在這段代碼中,a()中的返回值是一個匿名函數(shù),這個函數(shù)在a()作用域內部,所以它可以獲取a()作用域下變量name的值,將這個值作為返回值賦給全局作用域下的變量b,實現(xiàn)了在全局變量下獲取到局部變量中的變量的值

再來看一個閉包的經典例子

在這里插入圖片描述

一般情況下,在函數(shù)fn執(zhí)行完后,就應該連同它里面的變量一同被銷毀,但是在這個例子中,匿名函數(shù)作為fn的返回值被賦值給了fn1,這時候相當于fn1=function(){var n = 0 … },并且匿名函數(shù)內部引用著fn里的變量num,所以變量num無法被銷毀,而變量n是每次被調用時新創(chuàng)建的,所以每次fn1執(zhí)行完后它就把屬于自己的變量連同自己一起銷毀,于是乎最后就剩下孤零零的num,于是這里就產生了內存消耗的問題

再來看一個經典例子-定時器與閉包

寫一個for循環(huán),讓它按順序打印出當前循環(huán)次數(shù)


按照預期它應該依次輸出1 2 3 4 5,而結果它輸出了五次5,這是為什么呢?原來由于js是單線程的,所以在執(zhí)行for循環(huán)的時候定時器setTimeout被安排到任務隊列中排隊等待執(zhí)行,而在等待過程中for循環(huán)就已經在執(zhí)行,等到setTimeout可以執(zhí)行的時候,for循環(huán)已經結束,i的值也已經編程5,所以打印出來五個5,那么我們?yōu)榱藢崿F(xiàn)預期結果應該怎么改這段代碼呢?(ps:如果把for循環(huán)里面的var變成let,也能實現(xiàn)預期結果)

引入閉包來保存變量i,將setTimeout放入立即執(zhí)行函數(shù)中,將for循環(huán)中的循環(huán)值i作為參數(shù)傳遞,100毫秒后同時打印出1 2 3 4 5

那如果我們想實現(xiàn)每隔100毫秒分別依次輸出數(shù)字,又該怎么改呢?

在這段代碼中,相當于同時啟動3個定時器,i*100是為4個定時器分別設置了不同的時間,同時啟動,但是執(zhí)行時間不同,每個定時器間隔都是100毫秒,實現(xiàn)了每隔100毫秒就執(zhí)行一次打印的效果。

②閉包作為參數(shù)傳遞

在這段代碼中,函數(shù)fn1作為參數(shù)傳入立即執(zhí)行函數(shù)中,在執(zhí)行到fn2(30)的時候,30作為參數(shù)傳入fn1中,這時候if(x>num)中的num取的并不是立即執(zhí)行函數(shù)中的num,而是取創(chuàng)建函數(shù)的作用域中的num這里函數(shù)創(chuàng)建的作用域是全局作用域下,所以num取的是全局作用域中的值15,即30>15,打印30

最后總結一下閉包的好處與壞處

好處

①保護函數(shù)內的變量安全 ,實現(xiàn)封裝,防止變量流入其他環(huán)境發(fā)生命名沖突

②在內存中維持一個變量,可以做緩存(但使用多了同時也是一項缺點,消耗內存)

③匿名自執(zhí)行函數(shù)可以減少內存消耗

壞處

①其中一點上面已經有體現(xiàn)了,就是被引用的私有變量不能被銷毀,增大了內存消耗,造成內存泄漏,解決方法是可以在使用完變量后手動為它賦值為null;

②其次由于閉包涉及跨域訪問,所以會導致性能損失,我們可以通過把跨作用域變量存儲在局部變量中,然后直接訪問局部變量,來減輕對執(zhí)行速度的影響

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 一、情景引入: 關于js的作用域,我們都知道: 1.js的作用域分兩種,全局和局部 2.在js作用域環(huán)境中訪問變量...
    追尋1989閱讀 255評論 0 1
  • 在上一篇文章“執(zhí)行環(huán)境和作用域”中,我試著梳理了執(zhí)行環(huán)境和作用域的關系。但實際上,文章中并沒有提到作用域,而是介紹...
    海痕閱讀 271評論 0 0
  • 首先,js閉包對于哪怕是有很多年前端開發(fā)經驗的人,也是很晦澀難懂的東西. 所以,我不敢保證能把你說明白,但是如果你...
    火鍋伯南克閱讀 492評論 0 1
  • 閉包是js中一個晦澀難懂的一個概念,網上關于閉包的文章也是抓一大把,每個人的文章卻又不盡相同,或者說,每個人的理解...
    coolcao閱讀 237評論 0 2
  • 在js中的學習中,總會遇到一個陌生又晦澀,然后還是陌生的詞匯,那就是閉包。 首先,什么是閉包? 其次,閉包的作用是...
    林llgb閱讀 1,687評論 0 1

友情鏈接更多精彩內容