JS中關于閉包的相關知識。如果你想?yún)⒓觲eb前面工作,那么JS幾乎是每場面試都會被問到的問題,接下來我們就一起來看一下。
問:請講一下你對閉包的認識
什么是閉包
答:
能夠讀取其他函數(shù)內部變量的函數(shù)。
稍全面的回答:
在js中變量的作用域屬于函數(shù)作用域, 在函數(shù)執(zhí)行完后,作用域就會被清理,內存也會隨之被回收,但是由于閉包函數(shù)是建立在函數(shù)內部的子函數(shù), 由于其可訪問上級作用域,即使上級函數(shù)執(zhí)行完, 作用域也不會隨之銷毀, 這時的子函數(shù)(也就是閉包),便擁有了訪問上級作用域中變量的權限,即使上級函數(shù)執(zhí)行完后作用域內的值也不會被銷毀。
這里涉及到對函數(shù)作用域的認識: js變量分為全局變量和局部變量;函數(shù)內部可以直接讀取全局變量,而在函數(shù)外部自然無法讀取函數(shù)內的局部變量
閉包解決了什么問題
1. 可以讀取函數(shù)內部的變量
2. 讓這些變量的值始終保持在內存中。不會在函數(shù)調用后被清除
可以通過下面的代碼來幫助理解上面所說的:
function addCounter() { let counter = 0 const myFunction = function () { counter = counter + 1 return counter } return myFunction } const increment = addCounter() const c1 = increment() const c2 = increment() const c3 = increment() console.log('increment:', c1, c2, c3); // increment: 1 2 3
在這段代碼中increment實際上就是閉包函數(shù)myFunction, 它一共運行了三次,第一次的值是1,第二次的值是2,第三次的值是3。這證明了,函數(shù)addCounter中的局部變量counter一直保存在內存中,并沒有在addCounter調用后被自動清除。
閉包的應用場景
在開發(fā)中, 其實我們隨處可見閉包的身影, 大部分前端JavaScript 代碼都是“事件驅動”的,即一個事件綁定的回調方法; 發(fā)送ajax請求成功|失敗的回調;setTimeout的延時回調;或者一個函數(shù)內部返回另一個匿名函數(shù),這些都是閉包的應用。
下面是具體應用的例子:
1. 取正確值問題
for (var i = 0; i < 10; i++) { setTimeout(function () { console.log(i) //10個10 }, 1000) }
怎么取到每一次循環(huán)的正確值呢? 閉包這樣用:
for (var i = 0; i < 10; i++) { ((j) => { setTimeout(function () { console.log(j) //1-10 }, 1000) })(i) }
聲明了10個自執(zhí)行函數(shù),保存當時的值到內部
2.使用閉包模擬私有變量
私有變量在java里使用private聲明就可以了, 但是在js中還沒有,但是我們可以使用閉包模擬實現(xiàn)。
var counter = (function () { var privateCounter = 0; function changeBy(val) { privateCounter += val } return { increment: function () { changeBy(1) }, decrement: function () { changeBy(-1) }, value: function () { return privateCounter } } })(); counter.value() //0 counter.increment() //1 counter.increment() //2 counter.decrement() //1
匿名函數(shù)已經(jīng)定義就立即執(zhí)行, 創(chuàng)建出一個詞法環(huán)境包含counter.increment、counter.decrement、counter.value三個方法,還包含了兩個私有項:privateCounter變量和changeBy函數(shù)。這兩個私有項無法在匿名函數(shù)外部直接訪問,必須通過匿名包裝器返回的對象的三個公共函數(shù)訪問。
閉包的缺點
1. 由于閉包會是的函數(shù)中的變量都被保存到內存中,濫用閉包很容易造成內存消耗過大,導致網(wǎng)頁性能問題。解決方法是在退出函數(shù)之前,將不再使用的局部變量全部刪除。
2. 閉包可以使得函數(shù)內部的值可以在函數(shù)外部進行修改。所有,如果你把父函數(shù)當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內部變量的值。
聯(lián)系客服