面试防抖这样答

361 阅读2分钟
  1. 前言
  2. 防抖概念
  3. 防抖应用场景
  4. 第一版:全局变量timer
  5. 第二版:闭包版
  6. 第三版:this版
  7. 第四版:event版

1、前言

节流和防抖用来处理一些频繁的事件触发,减少请求频率

  1. onclick,keyup,keydown等。如用户不断点击提交表单等操作
  2. window的resizescroll

2、防抖概念

通过设置定时器实现。如果用户点击按钮,设置定时器,在N秒内,当用户再次点击,清除定时器,再重新设置(在N秒内,无论用户点击多少次,只执行它的最后一次)。
简单理解:在事件触发N秒后执行,在N秒内又被触发,则重新计时

3、防抖应用场景

  1. 按钮提交场景:防止多次提交按钮,只执行最后提交的一次
  2. 搜索框联想场景:防止联想发送请求,只发送最后一次输入
  3. 浏览器滚动scroll,会不断调用绑定的事件,为减少请求不浪费资源,在滚动结束时,加载数据

4、第一版:使用全局变量timer

<button id="submit">按钮</button>
let timer = null
function debounce() {
  if (timer !== null) {
    clearTimeout(timer) // 在2秒内,再一次点击清除原来的timer
  }
  timer = setTimeout(() => {
    console.log('事件处理')
  }, 2000)
}
const submit = document.getElementById("submit")
submit.onclick = debounce // 在js中绑定函数后面不写()

5、第二版: 利用闭包实现一个防抖的方法

优化点:

  1. 将第一版的全局变量timer放到函数内部,使用闭包更改timer
  2. 业务逻辑和防抖方法写在一起了,后续业务逻辑变多不利于维护
function callBack() {
      console.log(this)
}
function debounce(func, wait) {
  var timer
  return function () {
    clearTimeout(timer)
    timer = setTimeout(() => {
      func()
    }, wait)
  }
}
const submit = document.getElementById("submit")
// 使用闭包,返回一个函数。要执行函数所以debounce()调用
submit.onclick = debounce(callBack, 1000)

6、 第三版: 改变this指向,将this指向正确的对象

如果此时在callBack函数中输出this, this指向window。

function debounce(func, wait) {
  var timer
  return function () {
    var context = this
    clearTimeout(timer)
    timer = setTimeout(() => {
      func.call(context)
    }, wait)
  }
}
const submit = document.getElementById("submit")
submit.onclick = debounce(callBack, 1000)

7、第四版:event版

  1. JavaScript 在事件处理函数中会提供事件对象 event,我们修改下 callBack 函数
  2. callBack 函数可能是有返回值的,所以我们也要返回函数的执行结果
function callBack(e) {
  console.log(e) // 打印出对象
  console.log(this)
}
function debounce(func, wait) {
  var timer
  var result;
  return function () {
    let context = this;
    let args = arguments;

    clearTimeout(timer)
    timer = setTimeout(function () {
      // func函数可能是有返回值的,所以也要返回函数的执行结果
      result = func.call(context, args)
      timer = null
    }, wait)
    return result
  }
}
const submit = document.getElementById("submit")
submit.onclick = debounce(callBack, 1000)

如有错误或者不严谨的地方,欢迎指正。
本文参考冴羽的文章: https://juejin.cn/post/6844903480239325191