JS节流通用版

位置: 首页 > 代码集锦
[发布: 2026.6.25  作者: 马黑  阅读: 54]

什么是节流?

节流(Throttle)是一种限制高频事件触发频率的性能优化技术,确保函数在固定时间间隔内最多执行一次,相当于给函数加了“冷却时间”。常用于 scroll、resize、mousemove、keydown 等高频事件,避免页面卡顿和性能浪费。

先来体会高频事件的例子。下例,鼠标指针在方框内移动时会实时触发计数器函数的累加运算,计数结果高频率呈现在方框内,预览过程中请尝试将鼠标指针不停地在方框内绕圈移动,这时可以看到数字的变化速度非常之快:

<style>
    #mdiv { margin: auto; padding: 12px; width: 400px; height: 200px; display: grid; place-items: center; font-size: 36px; border: 1px solid gray; }
    .tMid { text-align: center; }
</style>

<h1 class="tMid">请在方框内移动鼠标指针</h1>
<div id="mdiv">0</div>

<script>
    let num = 0;
    const add = () => ++num; // 累加器
    const showRes = () => mdiv.innerText = add(); // 显示计数器结果
    mdiv.addEventListener('mousemove', showRes, 500);
</script>
    

mousemove 是鼠标指针移动事件,当它移动于特定元素之上,待运行的机制会被高频率触发,不加以节流可能产生非预期的效果甚至造成一些负面影响。要改变上例计数变化过快的效果,实现方法之一是给其降频,通过“节流”的机制让目标函数在一定时间间隔内只能运行一次。节流好比特定线路的公交车,在规定的事件间隔必定有一辆车子开出;或者也可以比喻为给花圃自动浇水的设备,令设备每隔一段时间自动喷水一次。

以下例子采用了通用的节流函数,该函数在 mouseover 监听事件中调用,作用于调用计数器并呈现计数结果的 showRes 函数,即每隔指定时间(wait毫秒)运行一次 showRes 函数(而 showRes 函数调用的是累加器函数):

<style>
    #mdiv { margin: auto; padding: 12px; width: 400px; height: 200px; display: grid; place-items: center; font-size: 36px; border: 1px solid gray; }
    .tMid { text-align: center; }
</style>

<h1 class="tMid">请在方框内移动鼠标指针</h1>
<div id="mdiv">0</div>

<script>
    let num = 0;

    // 函数 :累加器
    const add = () => ++num; 

    // 函数 :显示累加器当前运算结果
    const showRes = () => mdiv.innerText = add();
    
    // 函数 :节流(时间戳版)
    const throttle = (func, wait) => {
        let last = 0; // 上一次的时间戳
        return (...args) => {
            let now = Date.now(); // 当下的时间戳
            if (now - last >= wait) {
                func.apply(this, ...args); // 执行传入的目标函数
                last = now; // 重置时间戳
            }
        };
    };

    mdiv.addEventListener('mousemove', throttle(showRes, 500));
</script>
    

节流函数还有另一个版本,计时器版,通用函数如下:

// 节流 :定时器版
const throttle = (func, wait) => {
    let timeout;
    return (...args) => {
        if (timeout) return; // 冷却机制(如果计时器存在不执行下面的代码)
        // 启动计时器
        timeout = setTimeout(() => {
            timeout = null; // 注销计时器以便后续重置
            func.apply(this, ...args); // 应用函数
        }, wait);
    };
};
    

定时器版(setTimeout)节流函数完全可以替代前例的时间戳版(Date.now)函数,效果一样。

节流与防抖都是降频处理高频事件,二者的核心区别在于:节流是在匀速执行目标函数,防抖则是延时执行目标函数——好比电梯的自动关门机制那样,只要还有人进电梯,所指定的间隔时间马上重置,即重新开始倒计时。

【说明】本文所讨论的节流函数属于基础班、简化版、通用版,它们还有多种演进版本,感兴趣的朋友可以网查。

前一篇: 使用svgdr动态绘制图案
下一篇: textarea模拟高亮关键字

发表评论:

  
 

评论列表 [0条]

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com