JavaScript中閉包的4個(gè)有用技巧分享
前言
當(dāng)談到JavaScript
編程中的高級概念和技巧時(shí),閉包(Closures
)是一個(gè)重要而有趣的主題。閉包是一種函數(shù)與其創(chuàng)建時(shí)的詞法環(huán)境的組合,它允許我們捕獲和保留局部變量,并在函數(shù)之外使用它們。在這篇文章中,我們將深入探討JavaScript
中閉包的4種有用技巧,以及如何應(yīng)用它們來解決各種問題和提高代碼質(zhì)量。
1. 解決循環(huán)中的問題
在JavaScript
中,循環(huán)中的變量作用域問題經(jīng)常會導(dǎo)致預(yù)期之外的結(jié)果。通常,使用var
聲明變量會導(dǎo)致循環(huán)中的變量共享相同的作用域,因此在異步操作中,這些變量可能會具有意外的值。
問題場景:
for (var i = 0; i < 3; i++) { setTimeout(() => { console.log(i); // 輸出什么? }, 1000 * i); }
上述代碼將在1
秒、2
秒和3
秒后分別打印出3
,三次都是相同的值。這是因?yàn)?code>setTimeout是異步的,它在循環(huán)結(jié)束后才執(zhí)行,此時(shí)i
的值已經(jīng)是3
。
解決方法:
使用閉包來保存每次迭代中的i
的值:
for (var i = 0; i < 3; i++) { ((n) => { setTimeout(() => { console.log(n); // 輸出0、1、2 }, 1000 * n); })(i); }
或者,更簡單的方式是使用let
來聲明循環(huán)變量,它將在每次迭代中創(chuàng)建一個(gè)新的作用域:
for (let i = 0; i < 3; i++) { setTimeout(() => { console.log(i); // 輸出0、1、2 }, 1000 * i); }
這2種方法都可以解決循環(huán)中的作用域問題。
2. 保存函數(shù)狀態(tài)
閉包還可以用于實(shí)現(xiàn)記憶功能,通過緩存計(jì)算結(jié)果來提高性能。這在需要重復(fù)計(jì)算的函數(shù)中特別有用。
問題場景:
實(shí)現(xiàn)一個(gè)累加器:
let sum = 1; function add(num) { sum += num; return sum; } console.log(add(1)); console.log(add(5));
每次調(diào)用add
時(shí),它都會將上次的值保存下來。但是這段代碼有潛在的問題,那就是sum
可能會被其他部分代碼無意中修改。那如何解決?
解決方法:
使用閉包就可以規(guī)避上面存在的問題且可以緩存已經(jīng)計(jì)算的值:
function calculator(val) { let sum = val; return function(num) { sum += num; return sum; } } const add = calculator(1); console.log(add(1)); //2 console.log(add(5)); //7
每次調(diào)用返回的函數(shù)時(shí),它都會將傳遞給它的數(shù)字加到總和中,并返回新的總和。
3. 封裝私有變量和屬性
在過去,為了保護(hù)對象的私有變量,常常使用閉包。通過閉包,可以將變量封裝在函數(shù)內(nèi)部,只能通過函數(shù)暴露的接口來訪問和修改。
問題場景:
function add() { let count = 0; count++; console.log(count); } add(); //輸出1 add(); //輸出1 add(); //輸出1
調(diào)用函數(shù),輸出的結(jié)果都是1
,但是顯然我們想要的效果是讓count
每次加1
的。那如何解決呢?
解決方法:
使用閉包來封裝私有變量:
function add(){ let count = 0; function a() { count++; console.log(count); } return a; } var res = add(); res() //1 res() //2 res() //3
add
函數(shù)返回了一個(gè)閉包a
,其中包含了count
變量。由于count
只在add
函數(shù)內(nèi)部定義,因此外部無法直接訪問它。但是,由于a
函數(shù)引用了count
變量,因此count
變量的值可以在閉包內(nèi)部被修改和訪問,這樣就可以防止它被惡意修改了。
4. 函數(shù)柯里化
函數(shù)柯里化是一種將接受多個(gè)參數(shù)的函數(shù)轉(zhuǎn)化為一系列接受一個(gè)參數(shù)的函數(shù)的過程。這也可以通過閉包來實(shí)現(xiàn)。
問題場景:
const add = (a, b, c) => { return a + b + c; } console.log(add(2, 3, 4)); // 輸出9
解決方法:
使用閉包來實(shí)現(xiàn)函數(shù)柯里化:
function curry(callback) { const args = []; return function curried(...newArgs) { args.push(...newArgs); if (args.length >= callback.length) { return callback(...args); } else { return curried; } }; } function add(a, b, c) { return a + b + c; } const curriedAdd = curry(add); console.log(curriedAdd(2)(3)(4)); // 輸出 9
函數(shù)柯里化使函數(shù)更加靈活,能夠逐步接受參數(shù),提高代碼的可重用性和可讀性。
總結(jié)
在本文中,我們深入探討了JavaScript
中閉包的4種有用技巧,以及如何應(yīng)用它們來解決各種問題和提高代碼質(zhì)量。這些技巧包括解決循環(huán)中的變量作用域問題,實(shí)現(xiàn)記憶功能以提高性能,封裝私有變量和屬性,以及使用函數(shù)柯里化來提高函數(shù)的靈活性。
閉包是JavaScript
中一個(gè)強(qiáng)大的概念,它允許我們在函數(shù)之外訪問和操作局部變量,從而解決了許多常見的編程問題。雖然閉包在JavaScript
中有著廣泛的應(yīng)用,但也需要小心使用,以避免潛在的內(nèi)存泄漏問題。確保在不再需要閉包時(shí),及時(shí)釋放對其的引用,以幫助垃圾回收器正常運(yùn)作。希望本文對你理解JavaScript
中的閉包和如何應(yīng)用它們有所幫助。
以上就是JavaScript中閉包的4個(gè)有用技巧分享的詳細(xì)內(nèi)容,更多關(guān)于JavaScript閉包的有用技巧的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Layui中templet中a的onclick參數(shù)傳遞的問題
今天小編就為大家分享一篇解決Layui中templet中a的onclick參數(shù)傳遞的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09javascript 中String.match()與RegExp.exec()的區(qū)別說明
最近看了javascript權(quán)威指南 里面的正則部分,match和exec方法有一些相同點(diǎn)和不同點(diǎn),在這里寫一下加深一下印象2013-01-01JavaScript建立一個(gè)語法高亮輸入框?qū)崿F(xiàn)思路
通常網(wǎng)站自帶的textarea編輯器不能滿足我們的需求比如高亮顯示代碼等,在這篇文章中,我將使用JavaScript庫ACE來創(chuàng)建一個(gè)輸入框效果,該腳本允許開發(fā)人員創(chuàng)建支持語法高亮的輸入框,感興趣的你可不要錯(cuò)過了哈2013-02-02基于Bootstrap+jQuery.validate實(shí)現(xiàn)表單驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了基于Bootstrap+jQuery.validate實(shí)現(xiàn)表單驗(yàn)證,感興趣的小伙伴們可以參考一下2016-05-05javascript中對象的定義、使用以及對象和原型鏈操作小結(jié)
這篇文章主要介紹了javascript中對象的定義、使用以及對象和原型鏈操作,結(jié)合實(shí)例形式總結(jié)分析了javascript對象操作的常用技巧,需要的朋友可以參考下2016-12-12超贊的動手創(chuàng)建JavaScript框架的詳細(xì)教程
這篇文章主要介紹了動手創(chuàng)建JavaScript框架的詳細(xì)教程,包括DOM和各種屬性的調(diào)試等各個(gè)方面,超級推薦!需要的朋友可以參考下2015-06-06一文秒懂JavaScript構(gòu)造函數(shù)、實(shí)例、原型對象以及原型鏈
這篇文章主要介紹了一文秒懂JavaScript構(gòu)造函數(shù)、實(shí)例、原型對象以及原型鏈的相關(guān)知識,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08