函数防抖:如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
函数节流 :保证如果电梯第一个人进来后,10秒后准时运送一次,这个时间从第一个人上电梯开始计时,不等待,如果没有人,则不运行
// 函数节流
var throttle = function(fn, interval) { //fn为要执行的函数,interval为延迟时间 var _self = fn, //保存需要被延迟执行的函数引用 timer, //定时器 firstTime = true; //是否第一次调用 return function() { //返回一个函数,形成闭包,持久化变量 var args = arguments, //缓存变量 _me = this; if(firstTime) { //如果是第一次调用,不用延迟执行 _self.apply(_me, args); return firstTime = false; } if(timer) { //如果定时器还在,说明上一次延迟执行还没有完成 return false; } timer = setTimeout(function() { //延迟一段时间执行 clearTimeout(timer); timer = null; _self.apply(_me, args); }, interval || 500); }; }; //使用 window.onresize = throttle(function() { //你要执行的代码 }, 500);
如果空闲,则可以正常触发方法执行。
如果有一个动作在执行,又触发了一个动作,则直接return。
通过关卡if(!canRun),等于就拿到了通行证。然后下一步的操作就是立马将关卡关上canRun=false。这样,其他请求执行滚动事件的方法,就被挡回去了。
接着用setTimeout规定最小的时间间隔300,接着再执行setTimeout方法体里面的内容,将canRun=true 释放关卡,让下一个执行者执行。
最后,等setTimeout里面的方法都执行完毕,才释放关卡canRun=true,允许下一个访问者进来。
这个函数节流的实现形式,需要注意的是执行的间隔时间是>=300ms。如果具体执行的方法是包含callback的,也可以将canRun=true这一步放到callback中。理解了函数节流的关卡设置重点,其实改起来就简单多了。
函数防抖
function _debounce(fn,wait){
var timer = null;
return function(){
clearTimeout(timer);
timer = setTimeout(function(){
fn();
},wait);
}
}
上面的弊端是如果页面太长那fn函数就长时间不能去执行 如果想让fn在一定时间内去执行一次 就需要下面的函数。
function _debounce(fn,wait,time){
var previous = null; //记录上一次运行的时间
var timer = null;
return function(){
var now = new Date();
if(!previous) previous = now;
//当上一次执行的时间与当前的时间差大于设置的执行间隔时长的话,就主动执行一次
if(now - previous > time){
clearTimeout(timer);//执行fn函数也要清除timer要不然 第二次触发的函数就执行了fn
fn();
previous = now;// 执行函数后,马上记录当前时间
}else{
clearTimeout(timer);
timer = setTimeout(function(){
fn();
},wait);
}
}
}
function _log(){
console.log(1)
}
window.onscroll = _debounce(_log,500)