这一次彻底搞懂JS中的防抖和节流(面试必问)

1,926 阅读2分钟

什么是防抖?

通过setTimeout的方式,在一定的时间间隔内,将多次触发变成一次触发。(通俗的说是在最后一次点击间隔规定时间之后才能再次成功触发,否则触发不成功)

防抖的实现思路

  1. 在防抖函数返回的函数的上级作用域设置一个定时器变量t置为null;
  2. 通过t来判断是否是第一次执行。
  3. 如果不是第一次执行,清空定时器
  4. 如果是第一次执行,则通过apply(this,arguments)进行执行.
  5. 最后设置定时器,规定时间之后将t设置为null,使得间隔时间之后t为null,间隔时间之后的点击变为第一次点击。

防抖实现代码(立即执行版)

const btn = document.querySelector('#input');

btn.addEventListener('click',debounce(submit,3000),false);

function submit(e) {
    console.log(1);
}
// 防抖函数:最后一次点击之后,3秒之内的点击都无效
function debounce(fn,timer) {
    let t = null;
    return function() {
        // 判断是否是第一次执行
        let firstClick = !t;
        // 如果不是第一次执行,则清空延时  之所以要清空延时就是要防止前面的定时器对最新的定时器产生影响,
        if (t) { clearTimeout(t)};
        // 如果是第一次执行则直接执行
        if (firstClick) {
            fn.apply(this,arguments)
        }
        // 在第一次点击之后 间隔的规定时间之后,才将t置为null 为下一次第一次点击做准备
        t = setTimeout(() => {
            t = null;                    
        },timer)
    }
}

codeSandBox在线演示

防抖实现代码(延迟执行版)

function debounce(fn,time) {
    let t = null;
    return function() {
        clearTimeout(t);
        t = setTimeout(() => {
            fn.apply(this,arguments);
        },time)
    }
}

什么是节流?

节流指的是减少一段时间内的触发频率。只有在上一次成功触发间隔规定时间之后,才能再次触发。

节流的实现思路

  1. 在返回函数的上级作用域定义一个初始时间值begin = 0;
  2. 获取当前时间戳,如果(当前时间戳 - 初始值 > 规定时间间隔)则通过apply修改this指向并传参;
  3. 修改初始值为当前值;

节流实现代码

const btn = document.querySelector('#input');

btn.addEventListener('click',throttle(submit,2000),false);

function submit(e) {
    console.log(1);
}
// 节流函数:减少一段时间的触发频率,只有在上一次成功触发 间隔规定时间之后才能再次成功触发。

function throttle(fn,delay) {
    let begin = 0;
    return function() {
        let cur = new Date().getTime();

        if (cur - begin > delay) {
            fn.apply(this,arguments);
            begin = cur;
        }
    }
}

codeSandBox在线演示

节流与防抖的区别是什么?

  1. 防抖只在最后一次成功点击之后间隔规定时间之后才能再次成功触发,如果在时间间隔之内就被点击,需要重新间隔时间间隔才能点击。
  2. 节流则不同,节流只要在上一次成功触发规定时间之后点击就能再次触发,中间的触发不会产生影响。