JavaScript閉包的深度剖析與實(shí)際應(yīng)用小結(jié)
前言
本文將通過(guò)一系列代碼片段詳細(xì)探討閉包的概念、作用、原理及其優(yōu)缺點(diǎn),并結(jié)合具體實(shí)例進(jìn)行分析。希望通過(guò)這篇文章,讀者能夠?qū)﹂]包有更深刻的理解。
一、什么是閉包?
簡(jiǎn)單定義
閉包是指一個(gè)函數(shù)能夠記住并訪(fǎng)問(wèn)它的詞法作用域,即使這個(gè)函數(shù)在其詞法作用域之外執(zhí)行。換句話(huà)說(shuō),閉包讓一個(gè)函數(shù)可以訪(fǎng)問(wèn)另一個(gè)函數(shù)中的局部變量,即使外部函數(shù)已經(jīng)調(diào)用結(jié)束被釋放后,依然可以訪(fǎng)問(wèn)這些變量。
代碼示例1:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> function fn(){ var a = 3; return function (){ // 閉包函數(shù) return a; } } function fun(){ var ff = fn(); // function me(){return a;} alert(ff()); // 輸出3 } fun(); </script> </body> </html>
代碼解析:
fn
函數(shù)內(nèi)部定義了一個(gè)局部變量a
和一個(gè)匿名函數(shù)(閉包)。- 匿名函數(shù)返回
a
的值。當(dāng)fn
被調(diào)用時(shí),返回的是這個(gè)匿名函數(shù)。 - 在
fun
函數(shù)中,ff
是fn
返回的匿名函數(shù),調(diào)用ff()
會(huì)輸出3
,因?yàn)殚]包記住了a
的值。
二、閉包的作用
解決全局變量污染的問(wèn)題
閉包可以幫助我們將一些不需要暴露給全局作用域的變量封裝起來(lái),避免全局變量的污染。通過(guò)閉包,我們可以創(chuàng)建私有變量和方法,從而提高代碼的安全性和可維護(hù)性。
代碼示例2:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 全局變量累加和 var a = 1; function fn(){ a ++; } fn(); console.log(a); // 2 fn(); console.log(a); // 3 fn(); console.log(a); // 4 </script> </body> </html>
代碼解析:
- 這里使用了全局變量
a
來(lái)實(shí)現(xiàn)累加操作。每次調(diào)用fn
函數(shù)時(shí),a
都會(huì)增加1。 - 這種方式雖然簡(jiǎn)單,但會(huì)導(dǎo)致全局變量污染。如果多個(gè)函數(shù)都依賴(lài)于
a
,可能會(huì)引發(fā)不可預(yù)見(jiàn)的問(wèn)題。
使用閉包改進(jìn):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 局部變量累加和 function fn(){ var a = 1; return function(){ return ++ a; } } let fun = fn(); // function(){} console.log(fun()); // 2 console.log(fun()); // 3 console.log(fun()); // 4 </script> </body> </html>
代碼解析:
fn
函數(shù)內(nèi)部定義了一個(gè)局部變量a
和一個(gè)匿名函數(shù)(閉包)。- 匿名函數(shù)返回
a
的自增結(jié)果。每次調(diào)用fun
函數(shù)時(shí),都會(huì)執(zhí)行閉包,使得a
的值逐步增加。由于a
是局部變量,不會(huì)污染全局作用域,提高了代碼的安全性。
三、閉包的原理
瀏覽器的垃圾回收機(jī)制
當(dāng)一個(gè)函數(shù)執(zhí)行完畢后,通常其內(nèi)部的局部變量會(huì)被銷(xiāo)毀。但是,如果這些局部變量被其他函數(shù)引用,則它們不會(huì)被銷(xiāo)毀。這是因?yàn)殚]包的存在使得這些變量仍然處于活動(dòng)狀態(tài),瀏覽器的垃圾回收機(jī)制不會(huì)回收這些變量,直到所有引用它們的閉包都被銷(xiāo)毀。
代碼示例3:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> function fn(){ // 聲明一個(gè)數(shù)組 let arr = []; // 循環(huán)添加數(shù)據(jù) for(var i = 0;i < 5;i ++){ arr[i] = function(i){ // 0 1 2 3 4 return function(){ return i; }; }(i); } return arr; // 返回?cái)?shù)組 } let list = fn(); for(var i = 0,len = list.length;i < len;i ++){ console.log(list[i]()); // 01234 } </script> </body> </html>
代碼解析:
fn
函數(shù)內(nèi)部聲明了一個(gè)數(shù)組arr
,并通過(guò)循環(huán)為每個(gè)元素賦值。- 每個(gè)元素是一個(gè)閉包,該閉包接收一個(gè)參數(shù)
i
并返回一個(gè)匿名函數(shù)。匿名函數(shù)返回i
的值。 - 通過(guò)立即執(zhí)行函數(shù)表達(dá)式
(i)
,確保每次循環(huán)時(shí)傳遞的i
值是當(dāng)前的值,而不是最終的值。 - 最終,
list
數(shù)組中的每個(gè)元素都是一個(gè)閉包,調(diào)用這些閉包會(huì)依次輸出0
到4
。
四、閉包的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 變量長(zhǎng)駐內(nèi)存:閉包可以讓局部變量在函數(shù)執(zhí)行結(jié)束后仍然存在,這使得我們可以保存一些狀態(tài)信息,方便后續(xù)使用。
- 提供私有變量:通過(guò)閉包,我們可以創(chuàng)建私有變量和方法,避免全局變量的污染,提高代碼的安全性和可維護(hù)性。
缺點(diǎn)
- 內(nèi)存占用:由于閉包會(huì)讓變量一直存在于內(nèi)存中,可能導(dǎo)致內(nèi)存占用過(guò)大,尤其是在處理大量數(shù)據(jù)或長(zhǎng)時(shí)間運(yùn)行的應(yīng)用中。
- 內(nèi)存泄露:如果閉包沒(méi)有正確管理,可能會(huì)導(dǎo)致內(nèi)存泄露,尤其是在IE等老版本瀏覽器中更為明顯。
代碼示例4:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> function fn(){ // 聲明一個(gè)數(shù)組 let arr = []; // 循環(huán)添加數(shù)據(jù) for(var i = 0;i < 5;i ++){ arr[i] = function(){ return i; }(); } return arr; // 返回?cái)?shù)組 } let list = fn(); for(var i = 0,len = list.length;i < len;i ++){ console.log(list[i]); // 0 1 2 3 4 } </script> </body> </html>
代碼解析:
fn
函數(shù)內(nèi)部聲明了一個(gè)數(shù)組arr
,并通過(guò)循環(huán)為每個(gè)元素賦值。- 每個(gè)元素是一個(gè)立即執(zhí)行函數(shù)表達(dá)式,返回當(dāng)前的
i
值。 - 最終,
list
數(shù)組中的每個(gè)元素都是一個(gè)數(shù)值,分別是0
到4
。 - 這種寫(xiě)法避免了閉包帶來(lái)的內(nèi)存問(wèn)題,但也失去了閉包的功能。
五、總結(jié)與展望
結(jié)束語(yǔ)
通過(guò)上述代碼片段和解析,我們深入探討了JavaScript中的閉包概念、作用、原理及其優(yōu)缺點(diǎn)。閉包作為JavaScript中一個(gè)強(qiáng)大的特性,既能幫助我們解決許多編程難題,也需要注意其潛在的風(fēng)險(xiǎn)。合理使用閉包,可以在保證代碼安全性和性能的前提下,編寫(xiě)出更加簡(jiǎn)潔高效的程序。
未來(lái)展望
隨著JavaScript的發(fā)展,閉包的應(yīng)用場(chǎng)景也在不斷擴(kuò)展?,F(xiàn)代JavaScript框架如React、Vue等廣泛使用閉包來(lái)實(shí)現(xiàn)組件的狀態(tài)管理和生命周期管理。因此,深入理解閉包不僅是掌握J(rèn)avaScript的基礎(chǔ),更是邁向高級(jí)編程的重要一步。
到此這篇關(guān)于JavaScript閉包的深度剖析與實(shí)際應(yīng)用的文章就介紹到這了,更多相關(guān)js閉包應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序?qū)崿F(xiàn)點(diǎn)擊空白隱藏的方法示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊空白隱藏的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08JavaScript常用數(shù)組操作方法,包含ES6方法
這篇文章主要介紹了JavaScript常用數(shù)組操作方法,包含ES6方法,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒借鑒價(jià)值,需要的朋友可以參考下2018-09-09TypeScript內(nèi)置工具類(lèi)型快速入門(mén)運(yùn)用
TypeScript 中內(nèi)置了很多工具類(lèi)型,我們無(wú)需導(dǎo)入,可以直接使用。 其中的很多都是比較常用的,接下來(lái)我們根據(jù)使用范圍來(lái)一一介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-03-03uniapp小程序開(kāi)發(fā)組件封裝之自定義輪播圖效果
這篇文章主要介紹了uniapp小程序開(kāi)發(fā)組件封裝之自定義輪播圖,本文主要展示小程序端封裝輪播圖組件,使用的是uniapp進(jìn)行的開(kāi)發(fā),主要使用的是uniapp官網(wǎng)提供的swiper組件,需要的朋友可以參考下2023-02-02javascript中幾個(gè)容易混淆的概念總結(jié)
這篇文章主要介紹了javascript中幾個(gè)容易混淆的概念總結(jié),都是平時(shí)經(jīng)常遇到的問(wèn)題,這里推薦給大家,有需要的小伙伴參考下吧。2015-04-04微信小程序?qū)崿F(xiàn)拍照畫(huà)布指定區(qū)域生成圖片
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)拍照畫(huà)布指定區(qū)域生成圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07JavaScript數(shù)據(jù)結(jié)構(gòu)鏈表知識(shí)詳解
存儲(chǔ)有序的元素集合,但不同于數(shù)組,鏈表中的元素在內(nèi)存中不是連續(xù)放置的。每個(gè)元素由一個(gè)存儲(chǔ)元素本身的節(jié)點(diǎn)和一個(gè)指向下一個(gè)元素的引用(也稱(chēng)指針或鏈接)組成。下面通過(guò)本文給大家詳細(xì)介紹下,需要的朋友參考下2016-11-11