千家信息网

JavaScript中如何实现防抖和节流

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要为大家展示了"JavaScript中如何实现防抖和节流",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"JavaScript中如何实现防抖和节流"
千家信息网最后更新 2026年11月02日JavaScript中如何实现防抖和节流

这篇文章主要为大家展示了"JavaScript中如何实现防抖和节流",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"JavaScript中如何实现防抖和节流"这篇文章吧。

防抖

自动门感应到有人,打开门,并且开始5秒倒计时,在 5 s 内有另外一个人靠近到门,门感应到人,重新5秒倒计时

当事件被触发时,设定一个延迟,若期间事件又被触发,则重新设定延迟,直到延迟结束,执行动作 (防止多次触发)

web 应用上面

  • 改变页面大小的统计

  • 滚动页面位置的统计

  • 输入框连续输入的请求次数控制

一开始,点击按钮,console.log('pay money')

  

定义 debounce

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');}function debounce(func) {  // 在函数里面返回函数 , 只有当点击的时候才返回该函数  return function () {    func()  }}btn.addEventListener('click', debounce(payMoney))

设置延时

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');}function debounce(func, delay) {  return function () {    setTimeout(_ => func(), delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

清除延时:未能执行

原因

每次点击的时候就会执行返回函数里面的内容

每次点击的执行函数都是独立的,互不干涉

正因为他们之间没有联系,清除延时在这里完全没有起作用

要让这些独立的执行函数之间有联系,需要用到作用域链(闭包)

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');}function debounce(func, delay) {  return function () {    let timer    clearInterval(timer)    timer = setTimeout(_ => func(), delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

将 timer 放在返回函数的外围,这样在定义监听事件的同时,就定义了 timer变量

因为作用域链,所有独立的执行函数都能访问到这个timer变量

而且现在这个timer变量只创建了一次。是唯一的,我们只不过不断给timer赋值进行延时而已

每个清除延时就是清除上一个定义的延时,相当于多个函数共用同一个外部变量

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');}function debounce(func, delay) {  let timer  return function () {    clearInterval(timer)    timer = setTimeout(_ => func(), delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

此时的代码,this 是指向 window ?

因为回调的原因,运行时已经在Window下了

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');  console.log(this);}function debounce(func, delay) {  let timer  return function () {    clearInterval(timer)    timer = setTimeout(_ => func(), delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

解决办法

在 setTimeout 之前将 this 保存下来,此时的 this 是指向按钮的

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');  console.log(this);}function debounce(func, delay) {  let timer  // 只有当点击的时候,才返回此函数,所以 this 是指向按钮的  return function () {    let context = this    clearInterval(timer)    timer = setTimeout(_ => {      func.apply(context)    }, delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

考虑参数的问题,添加 arg

const btn = document.getElementById('btn')function payMoney() {  console.log('pay money');  console.log(this);}function debounce(func, delay) {  let timer  return function () {    let context = this    let args = arguments    clearInterval(timer)    timer = setTimeout(_ => {      func.apply(context)      console.log(context, args);    }, delay)  }}btn.addEventListener('click', debounce(payMoney, 1000))

节流

先触发一次后,防止接下来多次触发

滚动屏幕:统计用户滚动屏幕的行为来作出相应的网页反应

当用户不断进行滚动,就会不断产生请求,相应也会不断增加,容易导致 ⛔️ 网络阻塞

我们就可以在触发事件的时候就马上执行任务,然后设定时间间隔限制,在这段时间内不管用户如何进行滚动都忽视操作

在时间到了以后如果监测到用户有滚动行为,再次执行任务。并且设置时间闻隔

首先,写个改变页面尺寸的同时改变页面背景颜色的代码

function coloring() {  let r = Math.floor(Math.random() * 255)  let g = Math.floor(Math.random() * 255)  let b = Math.floor(Math.random() * 255)  document.body.style.background = `rgb(${r}, ${g}, ${b})`}window.addEventListener('resize', coloring)
function throttle(func, delay) {  let timer  return function () {    timer = setTimeout(_ => {      func()    }, delay)  }}window.addEventListener('resize', throttle(coloring, 2000))

判断触发的事件是否在时间间隔内

  • 不在:触发事件

  • 在:不触发事件

function throttle(func, delay) {  let timer  return function () {    // timer 被赋值了,直接返回,即不执行任务    if (timer) {      return    }    // 此时 timer 没被赋值,或 timer 已经执行完了      // 为 timer 赋值进行延时执行    timer = setTimeout(_ => {      func()      // 延迟执行以后我们要清空timer的值      timer = null    }, delay)  }}window.addEventListener('resize', throttle(coloring, 2000))

解决 this 指向(虽然当前的这个例子就是在 Window 下的)

function throttle(func, delay) {  let timer  return function () {    let context = this    let args = arguments    // timer 被赋值了,直接返回,即不执行任务    if (timer) {      return    }    // 此时 timer 没被赋值,或 timer 已经执行完了      // 为 timer 赋值进行延时执行    timer = setTimeout(_ => {      func.apply(context, args)      // 延迟执行以后我们要清空timer的值      timer = null    }, delay)  }}window.addEventListener('resize', throttle(coloring, 1000))

节流核心:事件间隔 另一种常见的时间间隔就是用Date对象

function throttle(func, delay) {  // 我们要和前一个时间点进行比较才能确定是否已经过了时间间隔  // 在返回函数外围,避免每次执行都被自动修改  let pre = 0  return function () {    // 保存执行函数当时的时间    let now = new Date()    // 刚开始,一定会执行    if (now - pre > delay) {      // 已经过了时间间隔,就可以执行函数了      func()      // 执行后,重新设置间隔点      pre = now    }  }}window.addEventListener('resize', throttle(coloring, 1000))

解决参数问题

function throttle(func, delay) {  let pre = 0  return function () {    let context = this    let args = arguments    let now = new Date()    if (now - pre > delay) {      func.apply(context, args)      pre = now    }  }}window.addEventListener('resize', throttle(coloring, 1000))

以上是"JavaScript中如何实现防抖和节流"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

函数 时间 事件 延迟 不断 任务 内容 变量 指向 时候 用户 页面 作用 就是 按钮 篇文章 独立 统计 倒计时 之间 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网电商科技 科技信息互联网 互联网医疗科技 互联网科技的英文 南京欣网互联网科技 腾讯科技 互联网女皇 有木互联网科技 米客互联网科技 科技伦理 互联网公司 汉立互联网科技有限公司联系电话 中盈科技互联网信息有限公司 新华互联网科技2019 现代互联网科技股 南平创想时代互联网科技有限公司 注册互联网科技公司经营范围大全 特约风豹互联网科技为什么扣费 世界互联网科技成果奖 北京天晋互联网科技有限公司 盐城市攀科互联网科技有限公司 河南商务圈互联网科技有限公司 中国互联网科技工作委员会毛军 新华互联网科技学校 金融科技与互联网金融 礼当家互联网科技 华脉科技工业互联网产品 青海省互联网新科技 西藏七维空间互联网科技有限公司 东莞新华互联网科技学校 互联网科技资金流入 广州梦谷互联网科技有限公司领导
0