js 函数防抖为什么要用闭包?

前言

前两天面试 ,面试官问我闭包的应用场景,我没有回答出来,最近看了看,其中一个场景就是函数防抖节流。

开始实验

函数防抖是指在函数被高频触发时当停止触发后延时n秒再执行函数(即每次触发都清理延时函数再次开始计时),一般用于resize,scroll,mousemove等
现在我们来实现一个功能
在输入框中输入一个字符,先显示waiting ,延迟1秒后 在下方输出 这个字符,(就像百度搜索框 单机版) 如图

在这里插入图片描述

<input type="text" id="input"/>
<div id="show"></div>

<script>
function delay(e) {
	    let timeout;
        timeout = setTimeout(()=>{
        	showInfo(e)
        }, 1000);
	}
	document.getElementById('input').addEventListener('input',delay)
	document.getElementById('input').addEventListener('input',function(){
		document.getElementById('show').innerHTML='waiting'

	})
</script>

如果没有使用防抖 就会像下面这样,多次调用就会添加多个settimeout到任务队列,1秒后执行,这样就会交叉显示了,当输入频率很快时就会这样。
(抖不抖???)
在这里插入图片描述
下面我们使用防抖技术

<input type="text" id="input"/>
<div id="show"></div>
<script>
	function showInfo(text){
		document.getElementById('show').innerHTML=text.target.value
	}
	function debounce(func, wait) {
	    let timeout;
	    return function () {
	        let context = this;
	        let args = arguments;

	        if (timeout) clearTimeout(timeout);
	        
	        timeout = setTimeout(() => {
	            func.apply(context, args)
	        }, wait);
	    }
	}

	document.getElementById('input').addEventListener('input',debounce(showInfo,1000))
	document.getElementById('input').addEventListener('input',function(){
		document.getElementById('show').innerHTML='waiting'
		
	})
</script>

在这里插入图片描述
这样才算正常。(稳!!)
现在来说为什么要用闭包?
我们可以看到 在上面代码中 将timeout变量变成全局变量也是可以实现的,如下代码。

<input type="text" id="input"/>
<div id="show"></div>

<script>
let timeout;
function delay(e) {
	if (timeout) clearTimeout(timeout);
       timeout = setTimeout(()=>{
       	showInfo(e)
       }, 1000);
}
	document.getElementById('input').addEventListener('input',delay)
	document.getElementById('input').addEventListener('input',function(){
		document.getElementById('show').innerHTML='waiting'

	})
</script>

因为这会出现如下问题:
1、对于一个页面上需要多个防抖函数的时候,需要写很多重复代码。
2、全局变量污染作用域

这时候闭包的优势就体现出来了,保护全局作用域不被污染,又能做到函数复用,我们只需要封装这么一个debounce函数就可以了:

function debounce(func, wait) {
		/*
		@ func 延迟执行的函数
		@ wait 延迟时间
		*/
	    let timeout;
	    return function () {
	        let context = this;
	        let args = arguments;

	        if (timeout) clearTimeout(timeout);
	        
	        timeout = setTimeout(() => {
	            func.apply(context, args)
	        }, wait);
	    }
	}
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值