前端百题斩【021】——通俗易懂的防抖与节流

简介: 前端百题斩【021】——通俗易懂的防抖与节流

性能一直是前端老生常谈的一个话题,其中有一个性能问题就是我们会频繁的触发一些事件,例如mousemove、scroll、resize等,虽然浏览器已经对这些事件的触发做了一些优化,但是如果在很短的时间内频繁的触发仍然会影响性能,这个时候就需要今天的主角:防抖和节流,利用它们来进行优化,提高性能。


21.1 防抖


640.jpg

21.1.1 定义


防抖就是将多次高频操作优化为只在最后一次执行(某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次)。通常的使用场景是:用户输入,只需在输入完成后做一次输入校验即可。


21.1.2 实现


防抖是将多次操作合并为一次操作完成,其原理就是维护一个计时器,在规定的时间后触发函数,但是在该规定时间内再次触发的话就会取消之前的定时器而重新设置,从而保证了只有最后一次操作能够被触发。其实现步骤如下所示:


  1. 利用闭包保存一个timer变量,然后返回一个函数(这个返回的函数就是后续频繁触发操作中调用的函数);
  2. 根据标志位判断是否第一次需要立即执行(因为有些情况是需要首次调用函数立即执行的,若没有该参数,就会在定时器到了之后才会执行);
  3. 当有新的触发时,若存在定时器,则清空该定时器;
  4. 设定一个新的定时器,重新计时。


function debounce(fn, wait, immediate) {
        let timer = null;
        return function (...args) {
            // 立即执行的功能(timer为空表示首次触发)
            if (immediate && !timer) {
                fn.apply(this, args);
            }
            // 有新的触发,则把定时器清空
            timer && clearTimeout(timer);
            // 重新计时
            timer = setTimeout(() => {
                fn.apply(this, args);
            }, wait);
        }
    }


21.1.3 效果预览

640.gif




观察效果图可以验证上述的理论知识:


  1. 防抖之后输出内容的频次降低了;
  2. 防抖之后,其在超过一定时间之后才会输出内容。


21.2 节流



640.jpg


21.2.1 定义


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


21.2.2 实现


节流函数的实现方式有两种:定时器版本、时间戳版本,这两者各有千秋,下面来简要实现一下。


21.2.2.1 定时器版本


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

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


// 定时器版本
function throttle(fn, wait) {
    let timer = null;
    return function(...args) {
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(this, args);
                timer = null;
            }, wait)
        }
    }
}


21.2.2.2 时间戳版本


时间戳版本的节流函数重点是利用闭包保存上一次的时间previous,具有两个特点:

  1. 开始触发后会立即执行(因为previous开始会被赋值为0);
  2. 停止触发后不再执行(因为该函数是同步任务,在触发的时候就会进行相应的判断,所以就不存在停止触发后再执行的情况)。
// 时间戳版本
function throttle(fn, wait) {
    // 上一次执行时间
    let previous = 0;
    return function(...args) {
        // 当前时间
        let now = +new Date();
        if (now - previous > wait) {
            previous = now;
            fn.apply(this, args);
        }
    }
}


21.2.3 效果预览

640.gif

观察效果图可以验证上述的理论知识:


  1. 节流确实降低了内容的输出频率,将高频变为低频;
  2. 时间戳版本的节流函数在首次会输出内容,但是最后一次的内容不会输出(谨慎使用);
  3. 定时器版本的节流函数确实不会立刻打印内容,而是超过一定时间之后才会打印;此外,其最后输入的内容会被打印出来。
相关文章
|
4月前
|
前端开发 UED 开发者
颠覆你的前端知识:防抖与节流的区别及实战解析!
【8月更文挑战第23天】在Web前端开发中,处理用户界面交互产生的事件可能会影响性能。为此,我们有两种优化方法:防抖(debounce)和节流(throttle)。防抖确保函数仅在事件停止触发一段时间后执行一次,适用于如搜索自动补全场景。而节流则确保函数按固定时间间隔执行,不管用户操作频率如何。本篇技术博客将深入解析两者差异并提供示例代码,帮助开发者更好地理解和应用这些技巧以提升应用性能和用户体验。
91 0
|
2月前
|
前端开发
前端常用方法防抖(debounce)和节流(throttle)的示例演示及应用场景说明
前端常用方法防抖(debounce)和节流(throttle)的示例演示及应用场景说明
38 0
|
3月前
|
缓存 边缘计算 前端开发
关于前端性能优化问题,认识网页加载过程和防抖节流
该文章详细探讨了前端性能优化的方法,包括理解网页加载过程、实施防抖和节流技术来提升用户体验和性能。
|
5月前
|
缓存 开发框架 前端开发
前端性能优化【前端必备】(含懒加载,手写防抖、节流等)
前端性能优化【前端必备】(含懒加载,手写防抖、节流等)
80 4
|
7月前
|
前端开发 JavaScript UED
【专栏】前端开发中,为解决用户操作引发的性能问题,常使用debounce(防抖)和throttle(节流)技术
【4月更文挑战第29天】前端开发中,为解决用户操作引发的性能问题,常使用debounce(防抖)和throttle(节流)技术。Debounce确保在一段时间内只执行最后一次事件触发的操作,减少不必要的执行,但有滞后性,适合搜索框实时搜索。Throttle则保证一定时间间隔内函数执行一次,保持固定频率,适用于滚动事件处理和窗口大小调整。两者可借助JavaScript或第三方库实现,需根据场景和需求选择并调整。正确使用能提升应用性能和用户体验。
62 1
|
7月前
|
前端开发 JavaScript UED
【前端面经】快手二面:节流和防抖知道吗?
【前端面经】快手二面:节流和防抖知道吗?
55 0
|
7月前
|
前端开发 UED
【Web 前端】防抖与节流的区别
【4月更文挑战第22天】【Web 前端】防抖与节流的区别
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
189 2
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
55 0
|
2月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。