面试题之函数防抖与节流

153 阅读3分钟

JS中得函数防抖

这是我参与更文挑战的第1天,活动详情查看:更文挑战

一、什么是函数防抖

概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

举个🌰,坐电梯的时候,如果电梯检测到有人进来(触发事件),就会多等待 10 秒,此时如果又有人进来(10秒之内重复触发事件),那么电梯就会再多等待 10 秒。在上述例子中,电梯在检测到有人进入 10 秒钟之后,才会关闭电梯门开始运行,因此,“函数防抖”的关键在于,在 一个事件 发生 一定时间 之后,才执行 特定动作。

为什么需要函数防抖

前端开发过程中,有一些事件,常见的例如,onresizescrollmousemove ,mousehover 等,会被频繁触发(短时间内多次触发),不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会浪费计算机资源,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。

除此之外,短时间内重复的 ajax 调用不仅会造成数据关系的混乱,还会造成网络拥塞,增加服务器压力,显然这个问题也是需要解决的。

实现原理

函数防抖的要点,是需要一个 setTimeout 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 clearTimeout 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。

    const debounce = (fn,wait)=>{
        let timer = null;
        return ()=>{
            if(timer != null){
                clearTimeout(timer);
            }
            timer = setTimeout(fn,wait)
        }
    };
    let handle = ()=>{
        console.log(Math.random());
    }
    window.addEventListener("resize",debounce(handle,1000))

一、什么是函数节流

函数节流是指每隔一段时间后执行一次,也就是降低频率,讲高频繁操作优化成低频操作,通常使用场景:滚动条事件、resize事件、动画等,通常每隔 100~500 ms执行一次。

实现原理

定时器版本的节流函数其重点是利用闭包保存timer变量,具有两个特点:

  • n秒后才会执行第一次(定时器到了时间后才会触发);
  • 停止触发后节流函数还会执行一次(因为该函数是延迟执行的,当停止触发时其任务已经到了队列中,所以停止后还会执行一次)。

使用场景

  • 懒加载、滚动加载、加载更多或监听滚动条位置;
  • 百度搜索框,搜索联想功能;
// 定时器方案
function throttle(fn,wait){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                fn.apply(context,args);
                timer = null;
            },wait)
        }
    }
}
    
function handle(){
    console.log(Math.random());
}
    
window.addEventListener("mousemove",throttle(handle,1000));