一张图搞清楚防抖和节流的区别

本文介绍了JavaScript中防抖(debounce)与节流(throttle)的技术实现及其应用场景。通过对比两种技术的不同之处,帮助读者理解何时选用防抖或节流,并提供实际案例,如输入框与按钮事件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、防抖(debounce)

指在时间n内,函数被触发多次,但是只执行一次,执行最新的触发。也就是在时间n内,碰到新的触发,就清除之前的,重新计时。

最简单的实现

function debounce(func, wait) {
    var timeout;
    return function () {
        clearTimeout(timeout)
        timeout = setTimeout(func, wait);
    }
}

修改this指向的

function debounce(func, wait) {
    var timeout;

    return function () {
        var context = this;

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context)
        }, wait);
    }
}
2、节流(throttle)

当持续触发某个事件时,会有规律的每隔时间n就执行一次函数。

最简单的实现

function throttle(func, wait) {
    var context, args;
    var previous = 0;

    return function() {
        var now = +new Date();
        context = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
        // 时间没到,啥都不干
    }
}
3、区别

对新触发执行的时间点不一样
在这里插入图片描述

上面的示例均为延迟防抖和延迟节流,特点在于执行时间点在周期最后。相对应的有前缘debounce和前缘throttle,这个执行时间点是立即执行的,对应上图中的1节点,之后的触发还是按照上图来,debounce的第二次执行会在停止触发之后的1s执行,throttle会在1s之后看有没有新的触发。

上文中代码来自于:

JavaScript专题之跟着 underscore 学防抖
JavaScript专题之跟着 underscore 学节流

4、lodash的使用

在这里插入图片描述
这句话我看了半天,大概理解是这样,当有触发时,会先执行一次leading的func, 后面如果又有n次触发,就又执行一次func,n的取值可以是n >= 1

5、防抖还是节流

以一个输入框为例,来测试lodash防抖和节流的区别:

在这里插入图片描述

快速在输入框内输入123,函数wait时间设置为1000,并保证输入在1s内完成。

_.debounceleadingtrailing结果分析
1truefalse打印了1只有开始执行,无法获得最终输入的数据,
默认falsetrue输入完成1s后, 打印了123在输入间隔时间小于1s的情况下,打印不会执行,直到你停止输入1s后,才打印
3truetrue打印1; 1s后打印123开始执行一次,停止输入后1s后执行1次
4falsefalse啥都不干!
_.throttleleadingtrailing结果分析
1truefalse打印了1同debounce
2falsetrue1s后, 打印了123从输入开始的1s后,打印1次,不同于debounce的停止输入后的1s打印
默认truetrue打印1; 1s后打印123开始执行一次,1s后再执行1次
4falsefalse同debounce

总结
throttle和debounce最大的区别在于最后打印的时间不一样。
所以,选择防抖还是节流,主要取决于具体的需求。

  1. 输入框需求,我肯定是想要在我输入完成之后再进行请求,而不是在我输入过程中,每隔1s就发一下请求,所以我会选择防抖,并设置wait为100或者200, 选择第2种配置。

  2. 对于按钮,我会设置wait为1000,使用第1种配置。这种防抖和节流函数从结果来看没有区别。

其他场景就看你需要什么样的效果了。

6、公用组件使用防抖和节流

比如我写了一个公用组件he-input,监听@input事件,并对调用debounce处理该事件,时间间隔为1000。

// he-input.vue 组件

<el-input v-model="value" @input="inputChange"></el-input>

methods: {
	inputChange: _.debounce(
	  function (v) {
	    console.log(v)
	  },
	  1000,
	  {
	    leading: false,
	    trailing: true,
	  }
	)
}

如果一个页面只有1个he-input,那没有问题。

当一个页面有两个甚至多个he-input的时候,就会有问题。

上面的时间间隔是1s,那么当我在1s内改变两个输入框的值,但结果只触发了一次打印,
主要原因是两个组件用了同一个debounce函数,两个组件在1s内先后触发,debounce只执行了最后一个触发,之前的都被忽略

因此,在公共组件内用防抖和节流要注意将其写在created或者mounted里面,让每一个实例都有其各自的函数。

created() {
	this.inputChange =  _.debounce(
	  function (v) {
	    console.log(v)
	  },
	  1000,
	  {
	    leading: false,
	    trailing: true,
	  }
	)
}
<think>嗯,用户想了解防抖节流区别以及它们的应用场景。首先,我得回忆一下这两个概念的基本定义。防抖节流都是用来优化高频触发事件的,但它们的实现方式适用场景有所不同。 防抖,我记得是当事件被频繁触发时,只有在停止触发一段时间后才会执行一次。比如搜索框输入,用户连续输入的时候,我们希望等到用户停止输入后再发送请求,这样可以减少不必要的请求次数。这时候应该用防抖对吧?而节流则是按照固定的时间间隔执行函数,不管事件触发有多频繁。比如窗口的resize或者滚动事件,如果每次变动都执行处理函数,可能会导致性能问题,所以用节流来限制频率,比如每隔200毫秒执行一次。 接下来要比较它们的区别防抖是延迟执行,直到事件停止触发;而节流是周期性地执行,不管事件是否还在触发。应用场景方面,防抖适合需要等待用户停止操作后再执行的情况,比如搜索建议、表单验证。节流适合在持续触发的事件中保持一定的执行频率,比如滚动加载更多内容或者游戏中的按键处理。 不过用户提供的引用资料里提到了一些具体的例子,比如引用[2]说节流用于resizescroll事件,防抖用于手机号邮箱验证。引用[4]也提到两者都是为了限制执行频次。需要确保我的回答这些资料一致,不能有冲突。比如防抖的应用场景应该包括输入验证,而节流用于高频事件如滚动。 然后要考虑如何组织内容,先分别解释防抖节流的概念,再对比它们的区别,最后给出应用场景。可能需要用一些例子来帮助理解。比如防抖的例子:按钮提交防止重复点击,用户连续点击只在最后一次点击后提交。节流的例子:页面滚动时每隔一段时间检查位置,而不是每次滚动都触发。 还要注意用户提到的引用标识,在回答中适当添加。比如在解释防抖时,引用[3][4]都有相关描述,可以在段落末尾加上引用标记。同样,节流部分可以引用[2][4]。 另外,用户可能想知道如何实现这两个函数。虽然问题没有直接问,但相关资料里有提到实现场景,可能需要在回答中简单说明,比如使用setTimeout来延迟执行,或者使用时间戳来控制执行频率。 最后,生成相关问题。根据用户提供的示例,可能需要问及两者的具体实现方法、实际应用案例以及如何选择使用哪一种。需要确保问题与主题相关,并且能够帮助用户进一步学习。 总结一下,回答的结构应该是:定义防抖节流,对比区别,应用场景,引用资料中的例子,最后生成相关问题。要注意使用正确的中文表达LaTeX格式,但用户的问题中没有数学公式,所以可能不需要使用数学表达式。不过系统级指令提到行内数学表达式要用$...$,但这里可能用不上,所以可能不需要处理这部分。</think>### 防抖节流的概念及区别 **防抖(Debounce)** 当事件频繁触发时,仅在最后一次触发后等待指定时间$t$,若期间无新触发则执行函数。若在$t$时间内再次触发,则重新计时[^3]。 **应用场景**: - 搜索框输入联想(等待用户停止输入后再请求) - 表单验证(输入停止后统一验证) - 窗口缩放结束后的布局调整[^2] **节流(Throttle)** 在单位时间$t$内,无论事件触发多少次,仅执行一次函数。后续触发需等待当前周期结束[^4]。 **应用场景**: - 页面滚动事件(如无限加载内容) - 游戏中的高频按键响应(限制操作频率) - 实时鼠标移动轨迹记录[^2] ### 核心区别 | **特性** | **防抖** | **节流** | |----------------|--------------------------|--------------------------| | **触发逻辑** | 等待触发停止后执行 | 固定时间间隔执行 | | **响应时机** | 最后一次触发后延迟$t$时间 | 周期内首次或末次触发[^4] | | **适用场景** | 避免重复执行最终操作 | 控制高频事件执行频率 | ### 技术实现对比 1. **防抖伪代码**: ```javascript function debounce(func, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); }; } ``` 2. **节流伪代码**: ```javascript function throttle(func, interval) { let lastTime = 0; return function(...args) { const now = Date.now(); if (now - lastTime >= interval) { func.apply(this, args); lastTime = now; } }; } ``` ### 选择原则 - 若需确保最终状态被处理(如提交按钮防重复点击)→ **防抖** - 若需保持周期性反馈(如滚动进度条更新)→ **节流**
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值