JS手写代码系列(三)节流防抖函数

571 阅读2分钟

debounce(防抖函数)

function debounce(fn,delay){
	let timer = null;
	return function(){
		clearTimeout(timer);
		timer = setTimeout(()=>{
			fn.apply(this,arguments)
		},delay)
	}
}

DFngiD.md.png

防抖函数:在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时

使用场景:

  • 用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次的查询ajax请求,这样可以有效减少请求次数,节约请求资源;

  • window的resize、scroll事件,不断地调整浏览器的窗口大小、或者滚动时会触发对应事件,防抖让其只触发一次;

throttle(节流函数)

function throttle(fn,time){
	let flag = true;
	return function(){
		if(!flag) return;   //flaga为false则结束
		flag = false;		//一次触发后变为false,在定时器改为true之前不再执行上下文内容
		setTimeout(()=>{
			fn.apply(this,arguments)
			flag=true;     //只有等到定时器事件触发,flag变为true,才有机会执行下一个定时器
		},time)
	}
}

时间戳方式:

function throttle(fn,time){
	let pre = Date.now();   //保存初始时间
	return function(){
		let cur = Date.now();  //保存执行函数体的时间
		if(cur-pre>time){		//计算时间间隔是否满足
			setTimeout(()=>{
				fn.apply(this,arguments);
				pre=cur;		//更新上一次的时间
			},time)
		}
	}
}

节流函数:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

应用场景

  • 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
  • 在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;

防抖是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,都会清除当前的 timer 然后重新设置超时调用,即重新计时。这样一来,只有最后一次操作能被触发
节流函数是通过一个时间戳,判断当前时间与上一次时间之差,如果在time后触发,就更新上一次时间。