防抖与节流

简介: 最近去面试,又遇到面试官问我防抖与节流了,而明明前几天就看过手写代码,却写不出来。

最近去面试,又遇到面试官问我防抖与节流了,而明明前几天就看过手写代码,却写不出来。有时候我在想,是不是自己太笨了


回归正题


防抖



先不说概念,按自己的理解,在单反里,有防抖机制。因为人在拿着单反的时候会手抖(单反重),按下快门的瞬间,照片会糊,所以有防抖机制,以防止新手把照片拍糊

单反中的防抖是防止抖动,让人拍出清晰的照片,JavaScript 中的防抖是为了什么?


同理,它的作用也是防止抖动。试想当你频繁触发一个事件时,就会引起不必要的性能损失,那么让该事件在停止触发后再触发,以此减少部分性能


防抖的定义


防抖就是要延迟执行,你一直操作触发事件一直不执行,当你停止操作等待多少秒后才执行


也就是说不管事件触发频率有多高,一定在事件触发 n 秒后执行。如果在事件触发的 n 秒又触发了这个事件,那就以新事件的事件为准,n 秒后才执行。总之,要等你触发完事件 n 秒内不再触发事件,它才执行


手写防抖


根据定义,我们知道要在时间 n 秒后执行,那么我们就用定时器来实现


function debounce(event, wait) {
    let timer = null;
    return function (...args) {
      clearTimeout(timer); // 清除setTimeout,使其回调函数不执行
        timer = setTimeout(() => {
            event.apply(this, args)
        }, wait)
    }
}


代码很简单,即当还在触发事件时,就清除 timer,使其在 n 秒后执行,但此写法首次不会立即执行,为其健壮性,需加上判断是否第一次执行的第三个参数 flag,判断其是否立即执行


function debounce(event, wait, flag) {
    let timer = null;
    return function (...args) {
        clearTimeout(timer)
        if (!timer && flag) {
            event.apply(this, args)
        } else {
            timer = setTimeout(() => {
                event.apply(this, args)
            }, wait)
        }
    }
}


防抖场景


窗口大小变化,调整样式


window.addEventListener('resize', debounce(handleResize, 200))


搜索框,输入后1000毫秒搜索


debounce(fetchSelectData, 300)


表单验证,输入 1000 毫秒后验证


debounce(validator, 1000)


防抖帝王库


两大工具库都有防抖源码,可供参考


lodash-debounce


underscore-debounce


节流



顾名思义,一节一节的流,就好似控制水阀,在事件不断触发的过程中,固定时间内执行一次事件


手写节流


因为是固定时间内执行一次时间,所以我们有两种实现方法,一用时间戳,二用定时器


时间戳


function throttle(event, wait) {
    let pre = 0;
    return function (...args){
        if (new Date() - pre > wait) {
            // 当 n 秒内不重复执行
            pre = new Date();
            event.apply(this, args)
        }
    } 
}


使用时间戳虽然能实现节流,但是最后一次事件不会执行


定时器


function throttle(event, wait) {
    let timer = null;
    return function (...args) {
        if (!timer) {
            timer = setTimeout(() => {
                timer = null;
                event.apply(this, args)
            }, wait)   
        }
    }
}


使用定时器实现节流,虽然最后一次能触发,但是第一次不会触发


时间戳 + 定时器


为解决第一次和最后一次都可以触发,把两者结合起来


function throttle(event, wait) {
    let pre = 0, timer = null;
    return function (...args) {
        if (new Date() - pre > wait) {
            clearTimeout(timer);
            timer = null;
            pre = new Date();
            event.apply(this, args)
        } else {
            timer = setTimeout(() => {
                event.apply(this, args)
            }, wait)
        }
    }
}


节流场景


scroll 滚动


window.addEventListener('scroll', throttle(handleScroll, 200))


input 动态搜索


throttle(fetchInput, 300)


节流帝王库


lodash-throttle


underscore-throttle


总结



防抖:只执行最后一次。事件持续触发,但只有等事件停止触发后 n 秒后才执行函数

节流:控制执行频率。持续触发,每 n 秒执行一次函数


对比图:


image.png


防抖节流对比图


线上demo(司徒正美的demo):防抖节流


参考资料



[1] lodash-debounce: https://github.com/lodash/lodash/blob/master/debounce.js


[2] underscore-debounce: https://github.com/jashkenas/underscore/blob/master/modules/debounce.js


[3] lodash-throttle: https://github.com/lodash/lodash/blob/master/throttle.js


[4] underscore-throttle: https://github.com/jashkenas/underscore/blob/master/modules/throttle.js


[5] 防抖节流: https://azhubaby.com/demo/防抖与节流/index.html


[6] awesome-coding-js: www.conardli.top/docs/JavaScript/节流.html


[7] 防抖节流场景及应用: https://www.zoo.team/article/anti-shake-throttle


[8] 函数防抖与函数节流: https://zhuanlan.zhihu.com/p/38313717

相关文章
|
11天前
|
数据采集 人工智能 安全
|
6天前
|
机器学习/深度学习 人工智能 前端开发
构建AI智能体:七十、小树成林,聚沙成塔:随机森林与大模型的协同进化
随机森林是一种基于决策树的集成学习算法,通过构建多棵决策树并结合它们的预测结果来提高准确性和稳定性。其核心思想包括两个随机性:Bootstrap采样(每棵树使用不同的训练子集)和特征随机选择(每棵树分裂时只考虑部分特征)。这种方法能有效处理大规模高维数据,避免过拟合,并评估特征重要性。随机森林的超参数如树的数量、最大深度等可通过网格搜索优化。该算法兼具强大预测能力和工程化优势,是机器学习中的常用基础模型。
330 164
|
5天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
332 155
|
6天前
|
编解码 人工智能 自然语言处理
⚽阿里云百炼通义万相 2.6 视频生成玩法手册
通义万相Wan 2.6是全球首个支持角色扮演的AI视频生成模型,可基于参考视频形象与音色生成多角色合拍、多镜头叙事的15秒长视频,实现声画同步、智能分镜,适用于影视创作、营销展示等场景。
411 4
|
14天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
940 7