js 节流 防抖

813 阅读2分钟

1.概念

节流(throttle)和防抖(debounce)都是优化性能的一种,如当页面resize时候我们要进行一些操作(重新排版或者进行别的操作),当输入框输入数据时我们要进行校验的时候需要使用这些技术。但他们触发函数的方式有些不同:

  1. 节流是让对应的函数每隔固定的时间执行一次。如页面resize时,我们只需要隔一定时间执行对应的函数就行。
  2. 防抖是让对应的函数在事件不再触发后执行对应的函数。如对input框中输入的字符串进行校验,等用户不在输入的时候一起发出去校验,而不需要输入一个字符就校验一次。

2.代码

一、节流

  1. 立即执行版(利用时间戳)(当resize时马上执行一次,但是在不触发resize后不在会执行)
function throttle(fn, wait) {  
    let cur, pre = 0;
    return function (...args) {  
        cur = +new Date();
        if(cur - pre >= wait) {
            fn.apply(this, args);
            pre = cur;
        }
    }
}
  1. 非立即执行版(利用setTimeout)(当resize时不会马上执行一次,但是在不触发resize后还会执行一次)
function throttle(fn, wait) {  
    let timer = null;
    return function (...args) {  
        if(!timer) {
            timer = setTimeout(() => {
                timer = null;
                fn.apply(this, args)
            }, wait);
        }
    }
}
  1. 结合版(当resize时会马上执行一次,在不触发resize后还会再执行一次)
   function throttle(fn, wait) {  
        let cur, pre = 0, timer = null;
        return function(...args) {
            cur = +new Date();
            if(cur - pre > wait) {
                fn.apply(this, args);
                pre = cur;
                if(timer) {
                    clearTimeout(timer);
                    timer = null;
                }
            } else if(!timer) {
                timer =setTimeout(() => {
                    fn.apply(this, args);
                    timer = null;
                }, wait);
            }
        }
    }

二、防抖

  1. 非立即执行版 (触发就清除掉上次的timer,重新绑定)
function debounce(fn, wait) {  
    let timer = null;
    return function (...args) {
        if(timer) {
            clearTimeout(timer); 
        }
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait);
    }
}
  1. 立即执行版
function debounce(fn, wait) {  
    let timer = null;
    return function (...args) {
        if(!timer) fn.apply(this, args);
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, wait);
    }
}
  1. 可配置版(默认非立即执行版)
function debounce(fn, wait, immediate = false) {  
    let timer = null;
    return function (...args) {
        clearTimeout(timer);
        if(immediate) {
            if(!timer) fn.apply(this, args);
        }
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, wait);
    }
}

参考文章

JS的防抖与节流