面试官直击:防抖与节流,你真的搞懂了吗?😱

前言

最近有一次面试,被狠狠拷打了,尤其是在讨论到页面性能优化时,关于防抖与节流的问题让我措手不及。为了避免再次遇到同样的尴尬,我决定系统地总结这方面的知识,力求简洁明了地分享出来。

认识防抖和节流

防抖(Debouncing)

防抖技术的核心思想是在一个指定的时间间隔内,如果事件被频繁触发,则只有最后一次触发才会执行相应的回调函数。换句话说,它确保了在连续快速的操作中,只执行一次回调。这对于避免不必要的计算或请求特别有用,比如用户在搜索框输入时,我们不希望每次按键都发送请求,而是等待用户停止输入一段时间后再发送。

节流(Throttling)

不同于防抖,节流限制了一个函数在一定时间内的调用次数。即无论事件被触发多少次,在规定的时间间隔内只会执行一次回调。例如,在处理滚动事件时,我们可以设置每秒只响应一次,从而减少浏览器的负担。

这两种技术的区别

  • 防抖:就像游戏里面的回城操作,如果在回城时间内再次点击回城(回城被打断),则会重新计算回城时间。也就是说,防抖会在你停止操作后的一段时间才执行。
  • 节流:类似于游戏里英雄的普通攻击,在一定时间内点击多次,也只能攻击一次。这意味着在设定的时间间隔内,即使事件被多次触发,也只会执行一次回调。

使用场景分析

  • 防抖

    • 搜索框自动完成建议:用户输入完毕后延迟一段时间再发送请求,避免每次按键都发送请求。
    • 表单验证:在用户停止输入后进行表单验证,而不是每次按键都验证。
    • 窗口大小调整:在用户停止调整窗口大小后执行相应的布局调整代码。
  • 节流

    • 页面滚动加载更多内容:当用户滚动页面时,每隔一定时间检查是否需要加载更多数据。
    • 鼠标移动事件:在游戏中跟踪玩家的鼠标移动,但不需要对每一次微小的移动都做出反应。
    • 触摸屏滑动:在触摸屏设备上,监听用户的滑动操作,但不需要对每一个细微的触摸点变化都做出响应。

实现防抖

防抖的实现原理非常简单,就是通过对要执行的函数进行延迟处理,以此来控制函数执行的次数。

具体流程如下:

  1. 定义debounce函数 :接受两个参数,一个是需要执行的函数func,另一个是等待的时间wait
  2. 内部逻辑
    • 使用let timeout;来存储定时器ID。
    • 返回一个新的函数,每当触发事件时调用此函数。
    • 在每次调用返回的函数时,首先清除之前设置的定时器(如果有)。
    • 设置一个新的定时器,在指定的wait时间后执行传入的func函数,并使用apply方法确保正确的上下文(this指向)和参数传递。
  3. 应用示例:将防抖函数应用于窗口大小调整事件,确保在用户停止调整窗口大小后3秒才执行回调。
js 复制代码
// 防抖
function debounce(func, wait) {
    let timeout;
    return function(...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

window.addEventListener('resize', debounce(() => { 
    console.log('window resize'); 
}, 3000));

实现节流

节流技术的实现原理也非常简单,就是通过设置一个固定时间间隔,在这个时间间隔内只能执行一次相应的回调函数。

具体流程如下:

  1. 定义throttle函数 :接受两个参数,一个是需要执行的函数func,另一个是限制的时间间隔limit
  2. 内部逻辑
    • 使用let lastExecutionTime = 0;来记录上一次执行的时间戳。
    • 返回一个新的函数,每当触发事件时调用此函数。
    • 在每次调用返回的函数时,获取当前时间now
    • 如果当前时间减去上次执行的时间大于或等于设定的limit,则执行传入的func函数,并更新lastExecutionTime为当前时间。
  3. 应用示例:将节流函数应用于滚动事件,确保每3秒内最多执行一次回调。
js 复制代码
// 节流
function throttle(func, limit) {
    let lastExecutionTime = 0;
    return function(...args) {
        const now = Date.now();
        if (now - lastExecutionTime >= limit) {
            func.apply(this, args);
            lastExecutionTime = now;
        }
    };
}

document.getElementById('scrollArea').addEventListener('scroll', throttle(() => {
    console.log('scroll event throttled');
}, 3000));

结语

掌握这些技巧不仅能够让你的网页运行得更加流畅,还能在面试中展现出你的专业水平和技术深度。希望本文能为你的前端开发之路提供一些有价值的参考!

相关推荐
悠然青年帅1 分钟前
基于Vue+Canvas实现的画板绘画以及保存功能
前端
JQShan1 分钟前
轻松搞懂 CocoaPods:Podfile 与 .podspec 的区别与最佳实践
面试·ruby·cocoapods
uhakadotcom3 分钟前
Godot 引擎:开源游戏开发的强大工具
后端·面试·github
screct_demo4 分钟前
详细讲一下 Webpack 主要生命周期钩子流程(重难点)
前端·webpack·node.js
小妖6665 分钟前
vue2的webpack(vue.config.js) 怎么使用请求转发 devServer.proxy
javascript·vue.js·webpack
uhakadotcom6 分钟前
frp 内网穿透工具:简介与实践
后端·面试·github
庸俗今天不摸鱼14 分钟前
【万字总结】构建现代Web应用的全方位性能优化体系学习指南(一)
前端·性能优化·cdn
大波V515 分钟前
vue3 使用docxtemplater 动态生成docx
前端·javascript·vue.js
1024小神16 分钟前
网页注入js代码实现获取请求的url和请求体内容,并获取响应体内容
前端·javascript
Fuzzyface17 分钟前
SPA是如何通过js不刷新页面但是更新浏览器的url的?
前端·javascript