前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常问面试题,防抖&节流的解答和实现

常问面试题,防抖&节流的解答和实现

作者头像
用户2231227
发布2022-09-26 11:09:09
2970
发布2022-09-26 11:09:09
举报
文章被收录于专栏:前端技术专栏-吴佳

前言

在面试的时候,防抖&节流被问及到的几率是非常大的,这也算是基础的问题吧。可以体现一个人的技术基础怎么样,所以通常应该会是一面的时候被问到,那么你是怎么回答的呢?或者让你实现你能写出来吗?

正文

什么是防抖?

所谓的防抖,指的就是在触发事件的一个时间段内,只要事件不再触发,才让这个回调函数去执行。所以说,如果在这个时间段里面重复触发事件,那么将会先清除上一次任务或者函数(也可以说是时间),然后重新去开启一个新的任务,当用户结束操作后,如果到了指定的这个时间段,那么就会执行一次这个函数。

所以也可以看成,在过滤用户的操作行为,当用户操作结束后,才去执行函数给予反馈。

防抖的实现

代码语言:javascript
复制
function debounce (fn, wait) {
  const timer = null
  return function (...agrs) {
    clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, agrs), wait)
  }
}

通过以上代码可以看到,在绑定事件函数的时候,我们执行debounce函数会传入一个参数和一个等待时间。然后内部还会返回一个函数,这个函数会通过事件执行,函数里面会接受到所有的参数args(是一个数组),每次执行函数前都会清理上一次的回调,然后开启一个新的回调。所以是通过定时器做的一个延迟执行,在定时器执行的时候就回调了我们业务逻辑,并且为了保证this的指向,使用了apply方法做了this的指向重置,这样一来就实现了防抖效果。以下是运用场景的一个demo

运用场景,示例:

代码语言:javascript
复制
<template>
  <input type="text" v-model="name" @input="debounce(cb, 1000)" />
</template>

<script>
  export default {
    data () {
        return {
          name: ''
        }
      },
    methods: {
      debounce (fn, wait) {
        const timer = null
        return function (...agrs) {
          clearTimeout(timer)
          setTimeout(() => fn.apply(this, agrs), wait)
        }
      },
      cb (e) {
        console.log(e, this.name)
        // 这里可以发送请求或者做一些其它处理     
      }
    }  
  }
</script>

什么是节流?

所谓的节流,指的是连续触发的事件内,在一个时间段只执行一次函数。就是说,节流是为了去稀释函数在事件内的执行频率。

所以可以看成,用户的不断操作在触发这个事件,但是函数的执行是让它在一个时间段中只执行一次,这样就可以让函数的执行频率降低到一个时间维度,所以就得到了节制流量的产生作用。

节流的实现

节流一般有两种方式实现,一种是时间戳的方式,另一种是定时器的方式。

时间戳的实现方式

代码语言:javascript
复制
function throttle(fn, wait) {
  let previous = 0
  return function (...args) {
    const now = Date.now()
    if ((now - previous) > wait) {
      fn.apply(this, args)
      previous = now
    }
  }
}

定时器的实现方式

代码语言:javascript
复制
function throttle (fn, wait) {
  let timer = null
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        timer = null
        fn.apply(this, args)
      }, wait)
    }
  }
}

以上就是两种实现方式:

第一种是使用时间戳计算得出有没有到指定时间,如果到了我们指定的执行时间,那么将会执行一次函数,并重置记录这一次的执行时间,否则将会等待到达时间才执行函数。

时间的计算公式:

现在时间 - 上一次执行函数时间 > 指定的时间 = true 将会执行一次函数

第二种是使用的定时器延迟执行,并通过开关来控制避免多次执行定时器,造成定时器的累积而变混乱。

所以开关的作用就是让定时器执行完当前这一个,才能开始下一个定时器的执行,这样就能控制住一个指定的时间段执行一次函数。

运用场景,示例:

代码语言:javascript
复制
<template>
  <div stype="padding: 10000px 0;"></div>
</template>

<script>
    export default {
      methods: {
        throttle(fn, wait) {
          let timer = null
          return function (...args) {
            if (!timer) {
              timer = setTimeout(() => {
                timer = null
                fn.apply(this, args)
              }, wait)
            }
          }
        },
        scrollCallback (e) {
          console.log(e)
          // 这里就可以去做一些处理
        }
      },
      mounted () {
        const evFn = this.throttle(this.scrollCallback, 1000)
        window.addEventListener('scroll', evFn)
        this.$once('hook:beforeDestory', () => {
          window.removeEventListener('scroll', evFn)
        })
      }      
    }
</script>
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端技术专栏 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档