JS:手搓一份节流函数

前端开发中,我们经常会遇到「高频触发事件」的场景 ------ 比如用户快速滑动页面、频繁点击按钮、实时输入搜索框等。如果直接在这些事件的回调函数中执行复杂逻辑(如 DOM 操作、接口请求),会导致浏览器频繁计算渲染,进而出现页面卡顿、响应延迟等问题。而「节流(Throttle)」作为前端性能优化的核心技术之一,能有效解决这类问题,它就像一个 "流量闸门",控制函数在指定时间内只执行一次,避免资源被过度消耗。

  1. 节流的定义

节流的核心逻辑可以概括为:在连续触发的事件中,确保函数在固定时间间隔内只执行一次。无论事件触发多少次(比如 1 秒内触发 100 次),函数最多只会执行 1 次,剩余的触发会被 "拦截",直到下一个时间间隔开启。​

举个生活中的例子:淋浴时调节水龙头的 "节水模式"------ 即使一直按住开关,水流也会按照固定频率间断流出,而不是持续喷涌。节流对函数的控制,就像这个 "节水模式",控制函数的 "执行频率"。

利用时间戳实现一个最后一次不执行的节流函数

梳理雏形

js 复制代码
    //节流函数和防抖函数都是传入,一个函数,一个时间,最后返回一个函数
    const throttle = (fn, delay) => {
    
    return function () {
            fn()
        }
}
    

核心逻辑: 通过记录「上次函数执行的时间戳」,每次事件触发时,对比当前时间与上次执行时间的差值,利用闭包机制保存上次的time:​

  • 若差值大于指定间隔 (delay),则立即执行函数,并更新上次执行时间;
  • 若差值小于间隔 ,则跳过本次触发。
js 复制代码
const throttle = (fn, delay) => {
    let time = 0;
    return function () {
        const date = Date.now()
        //初始时间 date-time> delay 恒成立 因为1970年1月1日 是时间戳 0 的时间
        if (date - time > delay) {
            time = date
            fn()
        }
    }
}

处理 this 指向和收集传入的参数就得到了,最后一次不执行的节流函数

js 复制代码
const throttle = (fn, delay) => {
    let time = 0;
    return function (...args) {
        const date = Date.now()
        if (date - time > delay) {
            time = date
            fn.apply(this, args)
        }
    }
}

如果业务中需要持续的数据处理,需要触发最后一次的函数,则需要加上定时器

  • 首次触发时,若没有定时器,则设置一个定时器,在间隔后执行函数;​

  • 连续触发时,若已存在定时器,则跳过本次触发;​

  • 定时器执行时,更新上次执行时间,并清空定时器,确保下次触发可正常执行。

沿用时间戳 节流的代码,增加变量记录剩余时间

js 复制代码
const throttle = (fn, delay) => {
    let timer = null;
    let time = 0;
    return function (...args) {
        if (timer) {
            clearTimeout(timer)
            //保证每一次执行的时候把之前预执行的函数取消
        }
        const now = Date.now()
        const remainTime = now - time - delay
        if (remainTime < 0) {
            timer = setTimeout(() => {
                time = Date.now()//记录当前执行的时间
                fn.apply(this, ...args)
            }, remainTime)
            //经过剩余时间后执行函数,完成最后一次的交互
        } else {
            time = Date.now()//记录当前执行的时间
            fn.apply(this, ...args)
        }
    }
}
    
相关推荐
研☆香6 小时前
聊一聊前端的常见字 关键字
开发语言·前端·javascript
日光倾7 小时前
TypeScript 随手记 —— 1
前端·javascript·typescript
Buke..10 小时前
【APP 逆向】哔哩哔哩 sign 参数逆向(下):OLLVM 混淆还原 sign 算法
java·javascript·爬虫·python·算法
前端炒粉12 小时前
长会话虚拟滚动与渲染优化
前端·javascript·vue.js
谙忆102412 小时前
图片裁剪总是跑偏?用 object-fit、object-position 和真实像素把坐标对齐
javascript·css·图像识别
花归去12 小时前
ant的a-table更改表格的高度
前端·javascript·html
sibylyue13 小时前
基于 Vben Admin 框架的 Vue 3 前端项目配置文件及常用命令
前端·javascript·vue.js
AC赳赳老秦15 小时前
多源数据关联挖掘:OpenClaw 打通工商、招投标、专利公开数据,挖掘企业业务关联关系
java·c语言·javascript·c++·python·deepseek·openclaw
光影少年16 小时前
react navite 内存泄漏:定时器、监听事件、订阅销毁
前端·javascript·react native·react.js·前端框架
breeze jiang16 小时前
Next.js 16 App Router 实战:从 About、Blog 动态路由到全局 404
开发语言·javascript·ecmascript