JS(函数节流throttle)

一、使用时间戳

function throttle1(fn, wait) {
    let previous = 0;
    return function () {
        let now = new Date().getTime();
        if (now - previous > wait) {
            fn.apply(this, arguments);
            previous = now;
        }
    }
}
  • 注:当鼠标移入的时候,事件立刻执行,每过 1s 会执行一次,如果在 4.2s 停止触发,以后不会再执行事件。

二、使用定时器

function throttle(fn, wait) {
    let timer;
    return function () {
        if (!timer) {
            timer = setTimeout(() => {
                timer = null;
                fn.apply(this, arguments);
            }, wait)
        }
    }
}
  • 注:当鼠标移入的时候,事件不会立刻执行,晃了 3s 后终于执行了一次,此后每 3s 执行一次,当数字显示为 3 的时候,立刻移出鼠标,相当于大约 9.2s 的时候停止触发,但是依然会在第 12s 的时候执行一次事件。
  • 区别:
    (1) 第一种事件会立刻执行,第二种事件会在 n 秒后第一次执行
    (2) 第一种事件停止触发后没有办法再执行事件,第二种事件停止触发后依然会再执行一次事件

三、两种结合使用


function throttle(fn, wait) {
    let timer;
    let previous = 0;
    let throttled = function () {
        let now = +new Date();
        // remaining 不触发下一次函数的剩余时间
        let remaining = wait - (now - previous);
        if (remaining < 0) {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            previous = now;
            fn.apply(this, arguments)
        } else if (!timer) {
            timer = setTimeout(() => {
                previous = new Date().getTime();
                timer = null;
                fn.apply(this, arguments);
            }, remaining);
        }
    }
    return throttled;
}


  • 注意:这个综合了两者的优势,鼠标移入能立刻执行,停止触发的时候还能再执行一次!

四、可配置(立即执行但结束后不执行,不立即执行但结束后要执行一次)

  • leading:false 表示禁用第一次执行
  • trailing: false 表示禁用停止触发的回调
function throttle(fn, wait, options = {}) {
    let timer;
    let previous = 0;
    let throttled = function () {
        let now = +new Date();
        // remaining 不触发下一次函数的剩余时间
        if (!previous && options.leading === false) previous = now;
        let remaining = wait - (now - previous);
        if (remaining < 0) {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            previous = now;
            fn.apply(this, arguments)
        } else if (!timer && options.trailing !== false) {
            timer = setTimeout(() => {
                previous = options.leading === false ? 0 : new Date().getTime();
                timer = null;
                fn.apply(this, arguments);
            }, remaining);
        }
    }
    return throttled;
}

  • 注意:那就是 leading:false 和 trailing: false 不能同时设置。

  • 节流:在规定时间内,保证执行一次该函数。

  • 防抖:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

你可能感兴趣的:(JS(函数节流throttle))