节流函数与防抖函数

防抖:多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行。

比如我们需要打印鼠标移动结束后光标的位置时候,我们经常用mousemove函数,但是我们在使用mousemove函数的时候,会打印出几十甚至上百次的鼠标光标的坐标。但是我们实际上需要的只是移动结束后的光标,那么这时候就需要引入防抖函数了。

实现原理:利用定时器,函数第一次执行时设定一个定时器,之后调用时发现已经设定过定时器就清空之前的定时器,并重新设定一个新的定时器,如果存在没有被清空的定时器,当定时器计时结束后触发函数执行。

代码如下:

function debounce(fn, wait = 50) {
    // 通过闭包缓存一个定时器 id
    let timer = null

    return function(...args) {
        if (timer) clearTimeout(timer)
      
        // 重新设定一个新的定时器
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait)
    }
}


节流:触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用

简单的实现原理:第一种是用时间戳来判断是否已到执行时间,记录上次执行的时间戳,然后每次触发事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经达到时间差,如果是则执行,并更新上次执行的时间戳,如此循环。

代码如下:

const throttle = (fn, wait = 50) => {
  // 上一次执行 fn 的时间
  let previous = 0
  // 将 throttle 处理结果当作函数返回
  return function(...args) {
    let now = +new Date()

    if (now - previous > wait) {
      previous = now
      fn.apply(this, args)
    }
  }
}


关于防抖如果需要第一次就立即执行,可修改为以下:

// immediate 表示第一次是否立即执行
function debounce(fn, wait = 50, immediate) {
    let timer = null
    return function(...args) {
        if (timer) clearTimeout(timer)
      
        // ------ 新增部分 start ------ 
        if (immediate && !timer) {
            fn.apply(this, args)
        }
        // ------ 新增部分 end ------ 
        
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait)
    }
}


其实在使用的时候完全可以用已有的underscore中的方法,但是在学习或者参加面试过程中,防抖跟节流还是比较常问到的知识点,会用不代表你懂,只有理解了,才是自己的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容