理解 JavaScript 中的节流和防抖:实现 `throttle` 和 `debounce` 函数

简介: 节流(throttle)是指在一定时间间隔内只执行一次函数,常用于控制高频事件触发频率,如滚动、窗口调整等。本文介绍其实现原理与代码示例。

什么是节流(throttle)?

节流是指在一定时间间隔内,确保某个函数不会被执行超过一次。即使在该时间间隔内多次触发函数,也只会执行一次。节流通常用于控制连续的事件触发频率,如滚动事件、窗口调整大小事件等。

实现 throttle 函数

下面是实现 throttle 函数的代码:

javascript

体验AI代码助手

代码解读

复制代码

function throttle(func, delay) {
  let lastTime = 0;  // 记录上一次执行的时间戳

  return function (...args) {
    const currentTime = new Date().getTime();  // 获取当前时间戳

    if (currentTime - lastTime >= delay) {
      func.apply(this, args);  // 执行原始函数
      lastTime = currentTime;  // 更新上一次执行的时间戳
    }
  };
}

// 示例用法
const throttledFunc = throttle(() => {
  console.log("Throttled function is executed!");
}, 1000);

// 触发频率高,但只在1秒内执行一次
setInterval(throttledFunc, 200);

代码解释

  1. 记录上一次执行时间lastTime 用于记录上一次函数执行的时间戳。
  2. 获取当前时间戳currentTime 获取当前的时间戳。
  3. 比较时间差:如果当前时间与上一次执行时间的差值大于或等于设定的延迟时间 delay,则执行函数 func
  4. 更新上一次执行时间:执行函数后,更新 lastTime

什么是防抖(debounce)?

防抖是指在连续的事件中,如果在指定时间内没有再次触发事件,则执行函数。如果在指定时间内再次触发事件,则重新计时。防抖通常用于控制输入框的输入事件处理等。

实现 debounce 函数

下面是实现 debounce 函数的代码:

javascript

体验AI代码助手

代码解读

复制代码

function debounce(func, delay) {
  let timeoutId;  // 记录定时器ID

  return function (...args) {
    clearTimeout(timeoutId);  // 清除之前的定时器

    timeoutId = setTimeout(() => {
      func.apply(this, args);  // 执行原始函数
    }, delay);
  };
}

// 示例用法
const debouncedFunc = debounce(() => {
  console.log("Debounced function is executed!");
}, 1000);

// 触发频率高,但只在最后一次触发后的1秒内执行一次
for (let i = 0; i < 5; i++) {
  setTimeout(debouncedFunc, 200 * i);
}

代码解释

  1. 记录定时器IDtimeoutId 用于记录当前的定时器ID。
  2. 清除之前的定时器:每次触发函数时,先清除之前的定时器。
  3. 设置新的定时器:重新设置一个定时器,在指定延迟时间 delay 后执行函数 func


转载来源:https://juejin.cn/post/7396247820900024355

相关文章
|
4月前
|
存储 JSON JavaScript
[go]byte类型, string 类型, json 类型
本文介绍了Go语言中byte类型的基本概念、特点及用法。byte是8位无符号整数,取值范围为0-255,常用于二进制数据操作,如网络通信和文件读写。文章还详细说明了byte与字符串的转换、遍历byte数据以及与其他类型间的转换。此外,探讨了Go中json.Marshal和json.Unmarshal函数实现[]byte与JSON间的转换,并对比了[]byte与JSON的区别,帮助开发者更好地理解其应用场景与差异。
155 2
|
4月前
|
监控 前端开发 Java
Spring拦截链的实现原理是什么?
拦截器是Spring MVC中处理请求的重要机制,通过拦截链可在请求的不同阶段插入自定义逻辑。本文详解拦截链的实现原理、核心组件如HandlerMapping、HandlerAdapter、DispatcherServlet和HandlerInterceptor的作用,以及拦截器在请求处理中的工作流程。了解这些内容有助于开发者更好地掌握Spring MVC的请求处理机制,并灵活应用于权限验证、日志记录等场景。
|
5月前
|
人工智能 运维 Java
SpringBoot+MySQL实现动态定时任务
这是一个基于Spring Boot的动态定时任务Demo,利用spring-context模块实现任务调度功能。服务启动时会扫描数据库中的任务表,将任务添加到调度器中,并通过固定频率运行的ScheduleUpdater任务动态更新任务状态和Cron表达式。核心功能包括任务的新增、删除与Cron调整,支持通过ScheduledFuture对象控制任务执行。项目依赖Spring Boot 2.2.10.RELEASE,使用MySQL存储任务信息,包含任务基类ITask及具体实现(如FooTask),便于用户扩展运维界面以增强灵活性。
165 10
|
3月前
|
人工智能 JavaScript 前端开发
js删除对象属性
本文介绍了JavaScript中删除对象属性及数组元素的多种方法,包括设置属性为undefined、使用delete操作符、对象解构、Reflect.deleteProperty方法以及数组的delete和splice操作。每种方法均有示例代码及关键特性说明,适用于不同场景下的属性或元素删除需求,帮助开发者更高效地处理对象和数组的操作。
133 0
js删除对象属性
|
3月前
|
人工智能 安全 Go
go快速上手:golang中的反射
本文深入解析Go语言反射机制,涵盖reflect包的核心类型与操作方法,通过实例演示如何动态获取类型信息、修改值及调用方法,并探讨反射的高级用法与注意事项,帮助开发者合理高效地使用反射。
135 1
|
3月前
|
存储 人工智能 Java
java之通过Http下载文件
本文介绍了使用Java实现通过文件链接下载文件到本地的方法,主要涉及URL、HttpURLConnection及输入输出流的操作。
215 0
|
5月前
|
人工智能 Java 数据库连接
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
253 10
|
5月前
|
Python
Python 中__new__方法详解及使用
__new__ 是 Python 中用于创建类实例的静态方法,在实例化对象时优先于 __init__ 执行。它定义在基础类 object 中,需传递 cls 参数(表示当前类)。__new__ 可决定是否使用 __init__ 方法或返回其他对象作为实例。特性包括:1) 在实例化前调用;2) 始终为静态方法。示例中展示了其用法及 Python2 和 Python3 的差异,强调了参数处理的不同。
210 10
|
5月前
|
人工智能 监控 算法
Go语言GC:三色标记法工程启示
本文深入探讨了Go语言中垃圾回收(GC)机制的性能影响及优化策略。首先分析了GC可能成为性能瓶颈的原因,如延迟敏感场景下的服务响应时间突增问题。接着介绍了三色标记法的核心概念与工作流程,以及并发GC面临的挑战和写屏障的作用。文章还详细讲解了Go GC的完整流程,并提供了多种工程实践启示,包括减少分配频率、预分配内存、避免过度使用指针、合理设置GOGC参数以及监控GC指标等优化方法。最后总结了GC优化的核心策略,帮助开发者构建更高效、可靠的Go应用。
123 5
|
6月前
|
存储 缓存 关系型数据库
MySQL为什么需要主键
本文介绍了MySQL中主键的重要性及最佳实践。主键用于唯一标识表中的每一行,其值必须唯一且不允许为空。主键有助于简化更新和删除操作,避免影响无关行。推荐使用与业务无关的自增ID作为Innodb表的主键,以优化存储结构、减少碎片并提高性能。此外,文章还提到不更新、不重用主键值以及避免使用可能变更的字段(如邮箱)作为主键的良好习惯。最后强调了紧凑索引结构对查询效率的关键作用。
202 0
MySQL为什么需要主键