SOURCE

console 命令行工具 X clear

                    
>
console
/**
 * 实现函数的节流 (目的是频繁触发中缩减频率)
 * @param {*} func 需要执行的函数
 * @param {*} wait 检测节流的间隔频率
 * @param {*} immediate 是否是立即执行 True:第一次,默认False:最后一次
 * @return {可被调用执行的函数}
 */
function throttle(func, wait) {
    let timer = null, previous = 0  // 记录上一次操作的时间点
    return function (...params) {
        let now = new Date()  // 当前操作的时间点
        let remaining = wait - (now - previous) // 剩下的时间
        if (remaining <= 0) {
            // 两次间隔时间超过频率,把方法执行

            clearTimeout(timer); // clearTimeout是从系统中清除定时器,但timer值不会变为null
            timer = null; // 后续可以通过判断 timer是否为null,而判断是否有 定时器

            // 此时已经执行func 函数,应该将上次触发函数的时间点 = 现在触发的时间点 new Date()
            previous = new Date(); // 把上一次操作时间修改为当前时间
            func.call(this, ...params);
        } else if (!timer) {

            // 两次间隔的事件没有超过频率,说明还没有达到触发标准,设置定时器等待即可(还差多久等多久)
            // 假设事件间隔为500ms,第一次执行完之后,20ms后再次点击执行,则剩余 480ms,就能等待480ms
            timer = setTimeout(_ => {
                clearTimeout(timer)
                timer = null // 确保每次执行完的时候,timer 都清 0,回到初始状态

                //过了remaining时间后,才去执行func,所以previous不能等于初始时的 now
                previous = new Date(); // 把上一次操作时间修改为当前时间
                func.call(this, ...params)
            }, remaining)
        }
    }
}

function myThrottle(func, wait) {
    let timer = null, pre = 0;
    return function (...args) {
        let now = new Date()
        let remaining = wait - (now - pre)
        if (remaining <= 0) {
            clearTimeout(timer)
            timer = null;
            pre = new Date();
            func.call(this, ...args)
        } else if (!timer) {
            timer = setTimeout(_ => {
                clearTimeout(timer)
                timer = null;
                pre = new Date();
                func.call(this, ...args)
            }, remaining)
        }
    }
}


document.querySelector('#btn').onclick = myThrottle(() => {
    console.log('你使劲儿点,我反正就是平均出现')
}, 1000)
<button id="btn">节流按钮,连续点击试试</button>