最近刚接触两个新概念函数防抖与函数节流,虽然这些内容网上可以搜到很多,大家都有自己的一套的理解方式,都写得很好,
而自己则想在理解的基础上自己把代码实现一遍,加深印象。
一、函数防抖
假如我们有这样的函数,控制台打印input的值
function getInput(){ console.log(document.getElementById('input').value); }
而当我们直接监听input的keyup事件调用getInput方法时,效果是这样的
每当我们输入一个字符,getInput就会被调用一次,这样频繁的请求在有些情况实际是不需要的,
而对这样反复执行的代码进行一个频率限制的方法之一便是函数防抖,下面看看函数防抖的代码实现
function debounce(func,delay){ var timeout = null; return function(){ clearTimeout(timeout); timeout = setTimeout(function(){ func.call(null); },delay); } }
这个函数作用是返回一个可供调用的函数,函数体是根据传入的delay延迟执行func,另外函数每次执行都进行clearTimeout的操作,
这样一来如果两次函数执行的间隔小于delay,那么timeout就会被重置,上一次设置的timeout将会被清除,那么只有本次设置的timeout会被执行
再来看看是如何调用的
document.getElementById('input').addEventListener('keyup',debounce(getInput,500));
再来看看效果,断断续续地输入内容
一直不断输入内容
可以看到当我们以较高频率输入内容的时候,控制台不再疯狂的打印内容了,这对于类似搜索框智能提示的应用场景是非常有帮助的,
避免了频繁的发起网络请求跟页面重绘
二、函数节流
第一种函数防抖的方式已经可以实现控制代码的调用频率,但是让我们来看看这样的调用
setInterval(debounce(getInput,600),500);
每500毫秒执行一次getInput经过防抖处理后的方法,基于函数防抖的原理这样的调用不会得到执行结果,
因为方法总是在600毫秒的延迟即将到来之前又被调用了,timeout被重置了,方法又被延迟600毫秒
所以还有另一种实现方式,既函数节流,先看看函数节流的代码实现
function throttle(func,delay){ var last = null; var timeout = null; return function(){ var now = new Date().getTime(); if(!last || now >= last + delay ){ last = now; func.call(null); } else{ last = last + delay; setTimeout(function(){ func.call(null); },last - now); } } }
再看看如何调用
setInterval(throttle(getInput,1000),500);
再看看效果
可以看到,即使定时器500毫秒执行一次,但是经过函数节流处理的getInput方法还是会1秒执行一次,
并且不会因为调用的间隔小于节流的时间间隔限制而导致方法不能执行。