在js中,DOM操作(onresize, onscroll….等等操作)是最消耗性能的,但是一些场景中同一事件会多次触发,为了减少操作,从而有了节流的概念。
函数节流的思想很简单:在每次出发的时候我们就开一个定时器,将DOM操作延迟,然后在下一次事件触发的时候,我们把这个定时器关掉,我们开关定时器,一直到一定的时机在触发事件。
javaScript 高级程序设计中的方法
function throttle (fn, context) { fn.tId && clearTimeout(fn.tId) fn.tId = setTimeout((() => { fn.call(context) }, 500) } // 很简单进入函数则清除定时器,重新创建一个定时器,然后把定时器id设置为fn,做缓存,等到用户事件不触发,500毫秒以后执行事件,并通过call修改执行this指向
网上流行的方法
function throttle (fn, delay) { var timer = null; return function () { var context = this, args = arguments; clearTimeout(timer) timer = setTimeout(() => { fn.apply(context, args) }, delay) } }
函数防抖
函数节流是一个很好用的方法,但是在某些场景下,我并不希望每次都是要事件结束后等待delay的时间后才执行回调,但是又希望减少操作,那么我们可以按照之前的思想,开关定时器即可
//第一种 我们根据时间触发函数 function throttle(fn , duration ,delay ){ var timer = null, // 记录下开始执行函数的时间 begin = new Date(); return function () { var context = this, args = arguments; // 记录下当前时间 current = new Date(); // 函数节流里的思路 clearTimeout(timer) // 记录下的两个时间相减再与duration进行比较 if (current-begin >= duration) { fn.apply(context , args) begin = current; } else { timer = setTimeout(() => { fn.apply(context , args) }, delay) } } } //第二种 根据触发的次数触发函数 function throttle(fn, maxLength){ //新建计数器,最大等待次数 var count = 0 maxLength = maxLength || 300; // 返回一个函数,实现作用域,缓存count的状态和maxLength return function () { var context = this, args = arguments, // 不满足条件 则不继续执行方法 count++; if(count < maxLength) return ''; // 当到达需要触发的时机以后我们触发函数,并将计数器归零 count = 0 fn.apply(context , args) } }