文章目录
前言
防抖与节流是前端面试的重难考点。希望在这篇博客我能把这两个概念讲清楚。
一,javascript定时器
在了解防抖与节流之前,我们需要先复习下定时器知识。如果这方面知识牢固,可以跳过。
定时器:js中的定时器有两种,分别是setTimeout()与setInterval()。下面将分别进行简单介绍
1.1 setTimeout()
格式:
setTimeout(callback, 3000);
其中,callback为回调函数,3000为毫秒(可替换)。
如:
setTimeout(function() {
alert('2s已经到了');
}, 2000)
即两秒后执行alert语句。
1.2 setInterval()
格式:
setInterval(callback, 3000);
如:
setInterval(function() {
alert('开端');
}, 1000);
即每隔一秒执行一次alert语句
1.3 两者区别
setTimeout()只执行一次,而setInterval()循环执行。
1.4 清除定时器
先定义一个定时器,再用clearInterval方法清除即可。如下:
//先定义一个定时器
var time = setTimeout(function() {
alert('123'};
,3000);
//清除定时器
clearInterval(time);
二,防抖
2.1 理解实例
在一般的塔防游戏中,英雄回城加血。点击回城按钮,固定一段时间后,比如5s,即可回城。但是回城中途,如果受到伤害,则停止回城。下次再回城则需重新经过5s才可以。
我们在回城中途可能会被频繁打断,但是只有经历完整5s,也就是最后一次能够回城成功。
2.2 防抖定义
结合上述实例,我们再来理解防抖策略:当事件触发后,延迟几秒后再执行回调。如果在这n秒内事件又被触发,则重新计时,是不是会清晰许多。
可以概括为:频繁触发,只触发一次
2.3 应用场景之输入框
请看下面几张图片:
我们想要搜索‘王者荣耀’,但是每写入一个字就会出现相应的搜索内容,却并不符合我们要查找的内容。这样会降低运行的效率。如何让我们能够一次达到目的,省略中间每个字搜索后查找呢?
这就是防抖策略的应用了。
2.4 实现防抖的步骤
step1: 预定义防抖timer
var timer = null;
step2: 定义防抖函数
funcion debounceSearch(keywords) {
//keywords为我们输入框内的内容
timer = setTimeout(function(){
},500)
}
step3: 触发事件清空timer
$('输入框').on('keyup', function(){
//当输入框内有输入的时候,意味着输入还未结束
clearTimeout(timer);//这个时候不需要查找,我们要查找的是最终结果的关键字,所以清除定时器
debouncesearch(keyword);//重新调用防抖函数
}
可能看注释会有点懵,但是请结合回城想一下。我们按下回城(5s),如果未满五秒取消,那么再次回城就会重新计时。当我们搜索‘王者荣耀’的时候(系统默认按一个按钮间隔5ms),先输入一个‘王’如果五毫秒内我们按下了‘者’,则5ms间隔被打断(定时器被清除),在我们按下‘者’时则重新计时5ms。以此类推,当我们按下‘耀’时,后面已经没有要输入的字了。按下耀后5ms没有操作,则意味着事件完成(回城成功)。最终则只执行一次,即搜索王者荣耀。
三,节流
3.1 理解实例
在玩王者荣耀时,每一个英雄在使用一个技能后,该技能都会有一个固定的冷却时间。冷却时间过后即可再次使用。如下:
在技能冷却时间,无论我们连续点击多少次都不会触发技能,而该技能只在单位时间内触发一次。
3.2 节流定义
综合上述实例,我们在玩游戏时英雄会有一定的技能冷却时间,从而减少了一段时间内事件的触发频率,而节流的理解则是减少事件的触发频率,有选择性执行一部分事件。
3.3 应用场景之公共厕所
请看以下几张图片:
当我们在外面上厕所时,门把手上都会有一个门阀,门阀为绿色代表卫生间里面没有人,外面的人可以进来上厕所。当有人进去上厕所后,关闭厕所门,门阀由绿色变为红色。则外面的人需要等待。
在我们每次准备进入厕所时,都需要判断门阀的颜色,如果门阀是绿色,我们可以进去,并将门阀变为红色。当我们出来时,门阀自动由红色变为绿色。下一个人判断门阀由红色变为绿色,下一个人进来上厕所。
这实际上就是一个简单的节流阀,它是事情判断的一个标准。那么我们再回到游戏中的实例,我们如何判断一个技能是否能够被使用?看它的技能冷却时间即可。当技能冷却时间大于0时,我们需要等待,当技能冷却时间为0时,我们可以使用。而这个时间,实际上也是一个节流阀。节流阀可以减少事件发生的频率,从而提高系统运行的效率,现在,你理解了吗。
3.4 实现节流的步骤
整体代码
$(document).on('mousemove', function(e) {
// console.log(e.pageX);
// console.log(e.pageY);
if(timer) {
return;
}
timer = setTimeout(function() {
$('#angel').css('top',e.pageY + 'px').css('left', e.pageX + 'px');
console.log('ok');
timer = null;
},16)
})
step1 先预定一个空的节流阀
var timer = null;
step2 设置一个计时器,时长为16ms,在执行完操作后设置定时器为空。
timer = setTimeout(function() {
//执行事件
console.log('ok');
timer = null;
},16)
step3 条件判断
if(timer) {
return;
}
当鼠标在屏幕上移动时,如果定时器不为空,则意味着16ms没有过去,操作还在执行中。此时不执行任何操作,返回return
如果操作执行完毕,定时器设置为空,则不满足判断,继续向下运行代码——重复运行计时器内的操作。这样可以保证此操作在16ms内运行一次,而不是每一次的鼠标移动都要运行一次,极大的提高了运行效率我们把这样的操作称为节流
四,共同点及区别总结
这里先再次重复一下两者定义:
防抖: 当事件触发后,延迟n秒后再执行回调,如果在这n秒内时间再次被触发,则重新计时。
节流:每个n秒执行一次,增加节流阀判断是否执行完毕,从而减少事件触发频率。
两者共同点:都用到计时器,都提高了系统运行效率。
两者区别:防抖是最后一次触发才可以运行,而节流则是每段时间运行一次,减少持剑触发频率,有选择性的执行操作
后记
希望这篇文章能够让读者更清晰直观的理解防抖与节流。最后,码字不易,可以关注作者,有好的文章及时推送给您!