Stevv's Blog

Do not go gentle into that good night

对闭包的理解以及使用

闭包的概念

闭包的概念可以理解为在一个函数里面又创建了另一个函数,这个创建的新函数可以访问到当前函数的变量。

下面是一段代码实例

1
2
3
4
5
6
7
8
9
10
11
function outerFunction() {
 var outerVar = 'I am outside!';

 function innerFunction() {
   console.log(outerVar);
}
 return innerFunction;
}

var inner = outerFunction();
inner(); // 输出 "I am outside!"

首先定义了一个函数outerFunction,在这个函数中定义了一个局部变量outerVar,并且在函数outerFunction中定义了一个函数

innerFunction他的作用是打印outerVar这个变量,这个时候innerFunction这个函数访问到了outerFunction函数中的局部变量,此时就构成了闭包

为什么要使用闭包

  • 使用闭包的第一用途就是可以让我们在函数外部访问到函数内部的变量,通过使用闭包,可以让我们在外部调用闭包函数,从而在外部访问到函数内部的变量。
  • 另一个用途就是使已经结束运行的函数的变量继续保存在内存中,这是因为闭包函数保留了对这个变量的引用。所以导致这个变量不会被回收。
  • 我们同样可以使用闭包来进行封装函数,这在项目中可能会用到。

注意:由于闭包会将函数中的变量保存在内存中,这对内存的消耗较大,所以注意不要滥用闭包

利用闭包写一个防抖函数

防抖函数使用的也比较多,我们在输入的时候当停止输入一段时间之后的时候我们才发送请求

这个功能就是当停止输入500毫秒时,才会将内容追加到output这个元素中。

下面这个就是对防抖函数进行了封装,使用了闭包的思想。

1
2
3
4
5
6
input.addEventListener("input", debounceFn((e) => {
     console.log(e);
   //获取输入的值
     const value = input.value;
     output.innerText += `发送API请求,参数:${value} \n`;
  }, 500));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

function debounce(fn, delay = 0) {
  //接收两个参数,一个fn函数,一个延时的事件delay
 // 返回一个新的防抖函数
 // 即使函数在 delay 时间段内多次被调用,也只会在最后一次函数被调用的 delay 时间结束后执行
 let timer = null;
  //返回值是一个函数,使用了闭包。
  //注意这里的参数是当input事件被触发时,会自动传入一个参数,这个返回的闭包函数接收这个参数。
 return function (e) {
   if (timer) clearTimeout(timer);
   timer = setTimeout(()=>{
       //闭包函数可以访问外部函数的传入的参数,调用这个函数并且将参数传入。
       fn(e)
       //fn函数就是传递的那个箭头函数,这样就达到了延时调用的目的
  },delay)
}

}

module.exports = debounce;

以上是我举得一个例子,我们在实际开发过程中会有很多场景会使用到闭包的思想,比如说使用promise封装一个函数,这个时候也会使用闭包的思想。