“节流”(Throttling)是一种处理高频触发事件的优化技术,它的核心思想是控制函数在一定时间内只执行一次,避免函数被过度调用。节流解决的是 “事件持续高频触发,但我们需要按固定频率执行函数” 的问题。

节流的本质是设置一个 “时间间隔”,当事件被触发时:

  1. 若距离上次执行函数的时间小于间隔,则忽略本次触发;

  2. 若距离上次执行函数的时间大于等于间隔,则执行函数并更新 “上次执行时间”。

es6之前的写法

        function throttle(callback, time, immediately){
            if(immediately === undefined){
                immediately = true;
            }
            if(immediately) {
                var t;
                return function() {
                    if(!t || Date.now() - t >= time) {
                        callback.apply(null, arguments);
                        t = Date.now();
                    }
                }
            } else {
                var timer;
                return function() {
                    if(timer) {
                        return;
                    }
                    var args = arguments;//利用闭包保存arguments
                    timer = setTimeout(function() {
                        callback.apply(null,args);
                        timer = null; // 清除定时器
                    },time);
                }
            }

        }

有两种计时方式,一种是通过时间戳判定,一种是通过定时器判定(立即执行和延迟执行)满足不同场景需求

es6之后的写法

function throttle(callback, time, immediately = true) {
    let timer;
    let lastTime
    return immediately
        ? function (...args) {
            if (!lastTime || Date.now() - lastTime >= time) {
                callback.apply(null, args);
                lastTime = Date.now();
            }
        }
        : function (...args) {
            if (timer) return;
            timer = setTimeout(() => {
                callback.apply(null, args);
                timer = null;
            }, time);
        };
}
  • 使用 ES6 默认参数(immediately = true)替代了手动判断 undefined 的逻辑,代码更简洁。

  • 采用 ...args 剩余参数语法收集参数,直接获得数组(相比 arguments 更便捷,支持数组方法)。

  • 使用 let 声明变量(timerlastTime),避免 var 的变量提升和作用域问题。

  • 通过三元运算符直接返回两种模式的函数,减少了 if-else 的嵌套层级,代码可读性更高。