基本概念
-
防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
-
节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。固定间隔时间去执行函数
分别适合什么场景?
- 节流:窗口的resize、 scroll
- 防抖:输入框input的内容校验
手写节流函数:函数节流主要有两种实现方法:时间戳和定时器
1. 时间戳写法:
当频繁触发事件时,第一次立即执行,而后再怎么频繁触发事件,也都是delay时间才执行一次。而当最后一次事件触发完毕后,事件不再被执行(最后一次触发事件与倒数第二次触发事件的间隔小于delay)
function throttle(fn, delay){
let last = 0;
return function(){
let now = Date.now();
if(now - last >= delay){
last = now;
fn.apply(this, arguments);
}
}
}
function handle(){
console.log(Math.random());//打印随机数
}
const throttleHandle = throttle(handle, 1000);
throttleHandle();
throttleHandle();
throttleHandle();
throttleHandle();//频繁调用
复制代码
2. 定时器写法:
当触发事件的时候,我们设置一个定时器,再次触发事件的时候,如果定时器存在,就不执行,直到delay时间后,定时器执行执行函数,并且清空定时器,这样可以设置下一个定时器。当第一次触发事件时,不会立即执行函数,而是在delay秒后才执行,而后再怎么频繁触发事件,也都是delay时间才执行。最后一次停止触发后,由于定时器的delay延迟,可能还会执行一次函数。
function throttle(fn, delay){
let timer = null;
return function(){
let context = this;
let args = arguments;
if(!timer){
timer = setTimeout(function(){
fn.apply(context, args);
timer = null;
},delay);
}
}
}
复制代码
3. 时间戳+定时器:
在节流函数内部使用开始时间startTime、当前时间curTime与delay来计算剩余时间remaining,当remaining<=0时表示该执行事件处理函数了(保证了第一次触发事件就能立即执行事件处理函数和每隔delay时间执行一次事件处理函数)。如果还没到时间的话就设定在remaining时间后再触发 (保证了最后一次触发事件后还能再执行一次事件处理函数)。当然在remaining这段时间中如果又一次触发事件,那么会取消当前的计时器,并重新计算一个remaining来判断当前状态。
function throttle(fn, delay){
let timer = null;
let startTime = Date.now();
return function(){
let curTime = Date.now();
//curTime - startTime 本次间隔已经过去多久
//剩余时间 = 完整间隔时间 - 本次间隔剩余时间
let remainning = delay - (curTime - startTime);
let context = this;
let args = arguments;
clearTimeout(timer);
if(remainning <= 0){
fn.apply(context, args);
startTime = null;
}else{
timer = setTimeout(fn, remainning);
}
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END