閉包作用:延長了局部變量的生命周期。如果沒有閉包,外部函數(shù)執(zhí)行完以后局部變量就釋放了,內(nèi)部函數(shù)調(diào)用不了局部變量報(bào)錯(cuò)
image.png

image.png
閉包應(yīng)用:
一、封裝私有變量---計(jì)數(shù)器
最簡單的用法,創(chuàng)建一個(gè)計(jì)數(shù)器:
function f1() {
var sum = 0;
var obj = {
inc:function () {
sum++;
return sum;
}
};
return obj;
}
let result = f1();
console.log(result.inc());//1
console.log(result.inc());//2
console.log(result.inc());//3
二、定義一個(gè)js模塊:
-
函數(shù)包裹模塊:一個(gè)函數(shù)中定義多個(gè)方法,通過return一個(gè)對象,將這些方法暴露出去,在使用時(shí)調(diào)用myModule方法得到這個(gè)暴露出去的對象
image.png
-
立即執(zhí)行函數(shù)包裹模塊:一個(gè)立即執(zhí)行函數(shù)中定義多個(gè)函數(shù),可以將這些函數(shù)放在一個(gè)對象中,將這個(gè)對象作為window的屬性暴露出去
image.png
三、函數(shù)防抖
在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計(jì)時(shí)??紤]維護(hù)全局純凈,可以借助閉包來實(shí)現(xiàn)保存計(jì)時(shí)器變量timer
如下代碼所示:
/*
* fn [function] 需要防抖的函數(shù)
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
//局部變量timer與使用了timer的函數(shù)構(gòu)成閉包
let timer = null
return function() {
if(timer){
clearTimeout(timer) //進(jìn)入該分支語句,說明當(dāng)前正在一個(gè)計(jì)時(shí)過程中,并且又觸發(fā)了相同事件。所以要取消當(dāng)前的計(jì)時(shí),重新開始計(jì)時(shí)
timer = setTimeOut(fn,delay)
}else{
timer = setTimeOut(fn,delay) // 進(jìn)入該分支說明當(dāng)前并沒有在計(jì)時(shí),那么就開始一個(gè)計(jì)時(shí)
}
}
}
四、回調(diào)函數(shù)傳參
定義行為,然后把它關(guān)聯(lián)到某個(gè)用戶事件上(點(diǎn)擊或者按鍵),根據(jù)不同需要傳入對應(yīng)參數(shù),實(shí)現(xiàn)回調(diào)函數(shù)傳參
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>測試</title>
</head>
<body>
<a href="#" id="size-12">12</a>
<a href="#" id="size-20">20</a>
<a href="#" id="size-30">30</a>
<script type="text/javascript">
function changeSize(size){
return function(){
document.body.style.fontSize = size + 'px';
};
}
var size12 = changeSize(12);
var size14 = changeSize(20);
var size16 = changeSize(30);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-20').onclick = size14;
document.getElementById('size-30').onclick = size16;
</script>
</body>
</html>

