节流和防抖两者的原理、区别及应用场景

334 阅读2分钟

节流

  • 原理: 事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定时间内,函数只能被调用一次,而且是最先被触发调用的那次。

  • 使用场景: 高频率的点击事件、选择器的联想输入、列表页面滚动加载更多等等。。。

方法一

/** 
*  fn 需要节流的函数    delay 间隔时间
*/
function throttle (fn, delay) {
    // 记录上次触发的时间
    let lastTime = 0;
    return function() {
        // 记录当前函数触发的时间
        let nowTime = Date.now()
         // 如果 (当前时间)- (上次触发时间) > 设定的间隔时间
        if(nowTime -lastTime > delay) {
            //修正this指向问题
            fn.call(this);
            // 同步执行介绍的时间
            lastTime = nowTime
        }
    }
}

方法二

   /** 
*  fn 需要节流的函数    delay 间隔时间
*/
function throttle (fn, delay) {
    // 设置一个用来判断是否可以执行的变量
    let flag = true;
    return function() {
       if(!flag) return false;   // 如果为false就不往下执行
       // 刚开始 flag 为 true,不会进入return, 然后将 flag 设置为 false,进入定时器, 
       // 在设置的定时器的时间间隔过了之后才会把 flag 设置会 true, 只有 flag 为 true 时才能再次执行事件函数
       flag = false
       setTimeout(()=> {
           fn.apply(this, arguments)
           flag = true
       }, delay)
    }
}

使用案例

function submit() {
    console.log("提交了")
}
doucument.getElementById("submitBtn").onClick = throttle(submit(), 500)

防抖

  • 原理: 多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行,也就是说,当一个事件被触发准备执行函数前,会等待一定的时间,如果没有再次被触发,那么就执行,如果被触发了,那就作废本次,重新从新触发的时间开始计算,再次等待设定的时间,直到最终执行。

  • 使用场景: 输入框输入后验证身份证号,手机号,邮箱等。。。

/** 
* 一个需要频繁触发的函数,在规定时间内,只能让最新的一次触发生效,之前的都作废
* fn 要被节流的函数   delay 规定的时间
*/
function debounce(fn, delay) {
    // 记录上一次的延时器
    let timer = null
    return function () {
        // 清除上一次的延时器
        clearTimeout(timer);
        // 重新设置新的延时器
        timer = setTimeout(function() {
            // 修正this指向问题
            fn.apply(this)
        }, delay)
    }
}
document.getElementById('btn').onclick = debounce(function() {
    console.log('按钮点击了')
}, 1000)

借鉴的原文文档链接: 前端必备八股文 - 丹青-水墨 - 博客园 (cnblogs.com)