什么是闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
function f1(){
var a = 9;
function f2(){
return a
}
return f2;
}
var result = f1()
let a = result() // a=9
闭包的应用场景
一、setTimeout函数传参
setTimeout(fn,delay)函数的第一个参数为函数fn,fn是不允许传入参数的。但是合理地使用闭包,也可以达到函数传参的目的。比如:
function f3(a){
return function f4(){
console.log(a)
}
}
var fn = f3(5)
setTimeout(fn,5000) //5秒后打印数字5
二、函数回调自定义行为
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>闭包</title>
</head>
<body>
<a href="#" id="size-16">16</a>
<a href="#" id="size-25">25</a>
<a href="#" id="size-60">60</a>
<script type="text/javascript">
function changeSize(size){
return function(){
document.body.style.fontSize = size + 'px';
};
}
var size16 = changeSize(16);
var size25 = changeSize(25);
var size60 = changeSize(60);
document.getElementById('size-16').onclick = size16;
document.getElementById('size-25').onclick = size15;
document.getElementById('size-60').onclick = size60;
</script>
</body>
</html>
三、函数防抖
在实际的业务场景中,为了防止一个事件连续重复的不断发生,常常需要使用函数防抖。在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数防抖</title>
</head>
<body>
<a href="#" id="debounce">函数防抖</a>
<script type="text/javascript">
document.getElementById('debounce').onclick = debounce(fn1,5000);
// 函数防抖
function debounce(fn,delay) {
let timer = null
return function(){
if(timer) {
clearTimeout(timer);
timer = setTimeout(fn,delay)
} else {
timer = setTimeout(fn,delay)
}
}
}
function fn1(){
console.log(5);
}
</script>
</body>
</html>
四、封装私有变量
下面通过闭包的形式封装一个私有变量,来实现js计数器的功能。
function r1(){
let sum = 0;
let obj = function(){
sum++;
console.log(sum);
return sum;
}
return obj
}
let result = r1();
result(); // 1
result(); // 2
result(); // 3
使用闭包要注意的问题
由于在闭包所在的作用域返回的局部变量不会被销毁,所以会占用内存。过度的使用闭包会迫使性能下降,因此建议大家在有必要的情况下再使用闭包。