概念

日常开发过程中,滚动事件做复杂计算频繁调用回调函数很可能会造成页面的卡顿,这时候我们更希望把多次计算合并成一次,只操作一个精确点,JS把这种方式称为debounce(防抖)和throttle(节流)

函数防抖

函数防抖(debounce):触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法

function debounce (fun,time) {var timeout = nullreturn function () {if(timeout !== null){clearTimeout(timeout)}timeout = setTimeout(fun,time)}}function fun(){console.log('====')}window.addEventListener('scroll', debounce(fun,1000))

该函数的意思就是,当你滚动一次,一秒后打印,但是如果在这一秒中,没打印之前,再次或者多次滚动,他会将之前的timeout清除掉,重新设置一个timeout,然后一秒后打印,而且这几次滚动只会打印最后一次(只打印一次)。

当持续触发scroll函数,handle函数只会在1秒时间内执行一次,在滚动过程中并没有持续执行,有效减少了性能的损耗

缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟

函数节流

函数节流(throttle):高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
实现函数节流我们主要有两种方法:时间戳和定时器

时间戳:
当高频事件触发时,第一次应该会立即执行(给事件绑定函数与真正触发事件的间隔如果大于delay的话),而后再怎么频繁触发事件,也都是会每delay秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。

function throttle(fun, delay) {let prev = Date.now()return function () {let context = this , args = argumentslet now = Date.now()if(now - prev > delay){prev = nowfun.apply(context, args)}}}function fun() {console.log('1')}window.addEventListener('scroll', throttle(fun, 1000))

当你进入页面时,开始计时,超过一秒,进行滚动,马上执行fun,记此次执行的时间赋值给prev,当下次滚动时,如果间隔没超过一秒,不会执行fun。

定时器:
当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行;直到delay秒后,定时器执行

function throttle(fun, delay) {var timer = nullreturn function () {var context = thisvar args = argumentsif(!timer){timer = setTimeout(function() {fun.apply(context,args)timer = null},delay)}}}function fun() {console.log('1')}window.addEventListener('scroll', throttle(fun, 1000))

连续滚动,当存在定时器时,不会执行fun,