JavaScript中的函数防抖和节流

 前言

面试中经常会被问到防抖和节流函数,本文主要讲解下防抖和节流函数的简单实现。

 一、防抖

函数防抖是指触发高频事件n秒后函数会执行一次,如果n秒内高频事件被再次触发,则重新计算时间;在整个过程中,事件函数只会被执行一次。

 使用场景:onMouseOver,onMouseMove,resize、input等

1. 非立即执行版

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>防抖</title>
  </head>
  <body>
    <div style="height: 1000px;width: 100%;">打开控制台  滚动页面  开始测试吧</div>
    <script>
      // 防抖功能函数
      function debounce (func, ms = 1000) {
        // 创建一个标记用来存放定时器的返回值
        let timer
        return function (...args) {
          // 每次当用户触发事件的时候,把前一个定时器清除
          if (timer) {
            clearTimeout(timer)
          }
          // 然后创建一个新的setTimeout
          // 这样就能保证触发函数的间隔时间内再次触发的话,就不会执行func函数
          timer = setTimeout(() => {
            func.apply(this, args)
          }, ms)
        }
      }

      // 有些需要防抖的工作,在这里执行
      const task = () => {
        console.log('执行了  防抖么')
      }

      const handlerScroll = debounce(task, 1000)
      document.addEventListener('scroll', handlerScroll)
    </script>
  </body>
</html>

2. 立即执行版

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div style="width: 100%;height: 2000px;">打开控制台,滚动页面 查看效果</div>
  <script>
    function debounce(func, ms = 1000) {
      let timer;
      return function(...args) {
        if(timer) {
          clearTimeout(timer)
        }
        let runNow = !timer
        timer = setTimeout(() => {
          timer = null
        }, ms)
        if(runNow) func.apply(this, args)
      }
    }
    
    const task = value => {
      console.log(`防抖 立即执行:${value}`)
    }

    const handleScroll = debounce(task, 1000)
    document.addEventListener('scroll', () => {
      handleScroll('参数')
    })
  </script>
</body>
</html>

3. 立即执行与非立即执行结合版

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>防抖(结合版-promise处理返回值)</title>
</head>
<body>
  <div style="width: 100%;height: 2000px;">打开控制台,滚动页面 查看效果</div>

  <script>
    function debounce(func, ms = 1000, immediate = false) {
      let timer, result
      let debounced = function(...args) {
        return new Promise(resolve => {
          if(timer) {
            clearTimeout(timer)
          }
          if(immediate) {
            let runNow = !timer
            timer = setTimeout(() => {
              timer = null
            }, ms)
            if(runNow) {
              result = func.apply(this, args)
              resolve(result)
            }
          } else {
            timer = setTimeout(() => {
              result = func.apply(this, args)
              resolve(result)
            }, ms)
          }
        })
      }

      // 取消
      debounced.cancel = function() {
        clearTimeout(timer)
        timer = null
      }

      return debounced
    }

    const task = num => {
      console.log('执行task函数')
      return num / 2
    }

    const handleScroll = debounce(task)

    document.addEventListener('scroll', () => {
      handleScroll(8).then(val => {
        console.log(`执行结果是:${val}`)
      })
    })
  </script>
</body>
</html>

二、节流

函数节流是指在高频事件触发期间,n秒内函数只会执行一次。

 使用场景:click、scroll等

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>节流</title>
  </head>
  <body>
    <div style="height: 1000px;width: 100%;">
      打开控制台 滚动页面 开始测试节流函数吧
    </div>

    <script>
      // 节流函数
      function throttle (func, ms = 1000) {
        // 通过闭包保存一个标记
        let canRun = true
        return function (...args) {
          // 在函数开头判断标志是否为true,不为true则中断函数
          if (!canRun) return
          // 将canRun设置为false,防止执行之前再被执行
          canRun = false
          setTimeout(() => {
            func.apply(this, args)
            // 执行完事件之后,重新将这个标志设置为true
            canRun = true
          }, ms)
        }
      }

      // 有些需要节流的工作 在这里执行
      const task = () => {
        console.log('执行了  节流')
      }

      const handlerScroll = throttle(task)
      document.addEventListener('scroll', handlerScroll)
    </script>
  </body>
</html>

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值