平时我们在开发中,会经常使用到resize和movesemove事件,这些事件会在短时间内频繁的执行事件绑定程序,我们知道频繁的操作DOM会带来很大的性能消耗,页面会促发回流和重绘。有时候页面会出现卡顿,在IE浏览器下可能直接崩溃。这时候节流函数就发挥作用了。
什么是函数节流?
简单讲就是让一个函数无法在短时间内连续调用,只有当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用。或者说你在操作的时候不会马上执行该函数,而是等你不操作的时候才会执行。
函数截流的原理
通过使用定时器,在操作的时候让函数延时执行,如果在这个时间内还在操作,则清除原来的定时器,再创建一个新的定时器执行
方式一:
最简单的操作方式,在操作的的时候清除上次的定时器,不操作的事后在执行callBack回调
//封装
/**
* @ { Function} callBack 回调程序
*/
function throttleFn(callBack){
clearTimeout(method.timer);
method.timer=setTimeout(()=>{
method()
},100)
}
//调用
window.onresize=function(){
throttleFn(callBack)
}
方式二
优势在于把延迟时间当做变量,而且使用闭包保护私有变量,缺点就是虽然使用apply把调用throttleFn时的this上下文传给执行函数,但毕竟不够灵活
//封装
/**
* @ { Function} callBack 回调程序
* @ { Number } delay 延时时间
* return { Function }
*/
function thorttleFn(callBack,delay){
var timer=null;
return function(){
var context=this;
clearTimeout(timer);
timer=setTimeout(()=>{
callBack.apply(context,arguments)
},delay)
}
}
//调用
window.onresize=thorttleFn(myFunc,300)
方式三(个人认为性能最优)
拓展深化函数节流
其实函数节流的出发点,就是让一个函数不要执行得太频繁,减少一些过快的调用来节流,减少性能消耗。当你在操作resize和mousemove事件的时候,浏览器其实是有设置一个时间间隔,这个时间是多少我们不清楚,而且他们没有提供参数去设置,所以需要我们在他们的基础上再去做一些改变。真正的节流应该是在可接受的范围内尽量延长这个调用时间,也就是我们自己控制这个执行频率,让函数减少调用以达到减少计算、提升性能的目的。假如原来是16ms执行一次,我们如果发现resize时每50ms一次也可以接受,那肯定用50ms做时间间隔好一点。
/**
* @ { Function} callBack 回调程序
* @ { Number } delay 延时时间
* @ { Number } intervalTime 间隔时间
* return { Function }
*/
function thorttleFn(callBack,delay,intervalTime){
var timer=null; // 定时器变量
var time=0; // 时间变量
return function(){
var context=this;
var curTime=new Date(); // 当前执行的时间
clearTimeout(timer); // 清除上次的定时器
if(!time){
time=curTime;
}
// 当前执行时间距离上次执行的时间是否大于等于间隔时间
if(curTime - time >= intervalTime){
time=curTime;
callBack.apply(context,arguments)
}else{
timer=setTimeout(()=>{
callBack.apply(context,arguments)
},delay)
}
}
}
//调用
window.onresize=thorttleFn(myFunc,50,300)