防抖

定义

  • 触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  • 也即是说,防抖的本质是延缓函数的触发。

    使用场景

  • 会被频繁触发的事件,但又不想让其频繁触发,比如输入搜索词、滚动、hover等等

    实现原理(文字版)

    前置知识:闭包

  1. 声明一个函数,例如 debounce;接收变量 回调函数func 和 防抖时间wait。
  2. 函数内声明变量 timeId,这个变量将供闭包使用,用来存储和销毁 setTimeout
  3. 通过将 debounce 函数的 return 置为 function,实现一个闭包,在闭包的匿名函数中,清除上一次的 setTimeout,开始本次的 setTimeout,setTimeout 中 调用回调函数 func。
  4. 声明over。
  5. 为对应的事件监听,执行 debounce 函数。保证对应事件发生时,执行的是debounce函数return的匿名函数。

    实现(代码版)

    1. // 声明
    2. const debounce = function (func, wait = 1000) {
    3. let timeId
    4. return function (...arg) {
    5. timeId && clearTimeout(timeId)
    6. let self = this
    7. timeId = setTimeout(() => {
    8. func.apply(this, arg)
    9. timeId = undefined
    10. }, wait)
    11. }
    12. }

    使用

    1. // in vue
    2. methods: {
    3. test: debounce(function(a, b) {
    4. console.log(a)
    5. console.log(b)
    6. })
    7. }

节流

定义

  • 触发事件后立即执行函数,如果在 n 秒中又触发了事件,不执行函数。
  • 也即是说,节流的本质是一段时间内只执行一次。

    使用场景

  • 按钮点击防连点

    实现

    1. const throttle = function (func, wait = 1000) {
    2. let timestamp = new Date().getTime()
    3. return function (...args) {
    4. const diff = new Date().getTime() - timestamp
    5. if (diff > wait) {
    6. func.apply(this, args)
    7. timestamp = new Date().getTime()
    8. }
    9. }
    10. }

    实现(注释版)

    1. const throttle = function (func, wait = 1000) {
    2. // 用于计算两次事件触发之间的时间差,
    3. let timestamp = 0
    4. return function (...args) {
    5. // 获取与上次函数执行的时间差
    6. const diff = new Date().getTime() - timestamp
    7. if (diff >= wait) {
    8. // 当函数被执行了,更新时间戳
    9. func.apply(this, args)
    10. timestamp = new Date().getTime()
    11. }
    12. }
    13. }