防抖节流的实现和使用

Posted by iris的博客 on October 15, 2023
layout:     post
title:      防抖节流的实现和使用
subtitle:   
date:       2023-10-15
author:     BY
catalog: true
tags:
    - 前端
    - Javascrit

防抖和节流是前端优化的一种常用方法。防抖,n秒后再执行该事件+n秒内若重新触发改事件,则重新计时。换句话说,如连续点击按钮,则按钮上绑定的事件永远不会实现。节流,n秒内不管点击多少次都只执行一次。lodash提供了debounce和throttle,这两个函数应该叫做“防抖化”和“节流化”函数,传入一个函数,使其具备防抖和节流的特性,简单实现一个防抖节流函数。

<!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>
    <button onclick="testDebounce()">测试防抖节流</button>
    <script>
        testDebounce = Debounce(() => {
            console.log('测试防抖节流')
        }, 3000)

        function Debounce(fn, interval = 1000) {
            let timer
            return function() {
                clearTimeout(timer)
                timer = setTimeout(() => fn(), interval)
            }
        }
    </script>
</body>
</html>

以上就简单实现了一个不带参数的防抖函数,这时候返回的函数是没有执行参数的,优化一波。

<!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>
    <button onclick="testDebounce('arg')">测试防抖</button>
    <script>
        testDebounce = Debounce((arg) => {
            console.log(arg)
        }, 500)

        function Debounce(fn, interval = 1000) {
            let timer
            return function() {
                let context = this, args = arguments
                clearTimeout(timer)
                timer = setTimeout(() => fn.call(context, ...args), interval)
            }
        }
    </script>
</body>

</html>

接下来实现一个节流函数,节流函数的效果是,不管点击多少次,只执行第一次,之后的若干时间内再点击无效。

<!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>
    <button onclick="testThrottle('arg')">测试节流</button>
    <script>
        Throttle = function (fn, interval = 1000) {
            let timer
            return function () {
                const context = this, args = arguments
                if (!timer) {
                    fn.call(context, ...args)
                    timer = setTimeout(() => {
                        timer = null
                    }, interval)
                }
            }
        }

        testThrottle = Throttle(function (arg) {
            console.log(arg)
        }, 2000)
    </script>
</body>

</html>

重点就是触发clearTimeOut的时机了,防抖中只要触发事件就清掉。而在节流中第一次成功触发才将flag位置为null。用时防抖是将定时器清掉,节流只要保证一段时间内不进入方法。总得来说防抖节流的实现都依赖于闭包和定时器。