节流、防抖形象记忆,and杂交版节流探秘!

节流

概念简述

在一段时间内只取用第一次的调用。

节流的字面意思就是当一次通行之后到达了阈值,就会开启节流阀门限制你通行。

形象记忆

就像你来到了某个人流量特别大的旅游景点,在一定的时段内,先来的人可以通行,到了人流限制点之后,人员均不得入内,得等待下一波放行时间。

实现原理

节流是借助闭包来实现的,通过闭包来缓存上一次触发回调的时间与当前时间进行比对限制回调执行。

重点

  1. 闭包:返回一个函数,缓存上次调用时间;
  2. 上次调用时间与本次调用时间比对;
  3. 触发传入的回调:使用apply将调用时的this指向回调函数,将arguments传入回调;
js 复制代码
// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval = 200) {
  // last为上一次触发回调的时间
  let last = 0
  // 将throttle处理结果当作函数返回
  return function () {
    // 记录当前调用时间戳
    let now = +new Date()
    // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
    if (now - last >= interval) {
      // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
      last = now;
      // this: 调用时的上下文, arguments 调用时传入的参数
      fn.apply(this, arguments);
    }
  }
}

// 用throttle来包装scroll的回调
const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)

使用场景推荐

  1. 滚动事件处理
  2. 鼠标移动事件
  3. 其他限制请求频率等需要控制函数执行频率的场景

防抖

概念简述

在一段时间内只取用最后一次的调用。

防抖这个概念很形象,防止你手抖误操作,在一段时间还给你改正的机会,会以你最后一次操作为准。

形象记忆

在高考填写志愿的时候,会你足够的时间让你慎重考虑之后填写,在填写期间你可以随意改变志愿,最终会以你最后一版志愿为准。

实现原理

防抖也是借助闭包来实现的,通过闭包来缓存定时器,调用将会被延迟执行,在这个延迟等待过程中如果你重复调用,上次的等待将会中断弃用,开启下一轮延迟执行。

重点

  1. 闭包:返回一个函数,缓存延迟定时器
  2. 回调执行时清除上一个定时器,setTimeout延迟执行本次回调
  3. 触发传入的回调:使用apply将调用时的this指向回调函数,将arguments传入回调
js 复制代码
// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
function debounce(fn, delay = 200) {
  // 定时器
  let timer = null
  // 将debounce处理结果当作函数返回
  return function () {
    // 每次事件被触发时,都去清除之前的旧定时器
    timer && clearTimeout(timer)
    // 设立新定时器
    timer = setTimeout(function () {
      // this: 调用时的上下文, arguments 调用时传入的参数
      fn.apply(this, arguments)
    }, delay)
  }
}

// 用debounce来包装scroll的回调
const better_scroll = debounce(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)

使用场景推荐

  1. 输入框搜索
  2. 按钮点击防止重复提交
  3. 其他需要等待用户停止操作后再执行的场景

杂交版节流

不知道大家最近都玩过植物大战僵尸杂交版没有,各种类型的杂交植物把植物大战僵尸又推向了新的高点。咱们也可以推出一个杂交版的节流(或者是杂交版防抖?此文统称为杂交版节流),融合了节流和杂交,妥妥的升级。

只要你弄懂了节流和防抖的原理,相信杂交版的节流你会很熟悉,杂交版的节流就是将防抖的逻辑增添进来了,所以它融合了节流和防抖的优点,在一段时间内,第一次操作将会被执行,如果你在这段时间内有别的操作,将会取最后一次的操作再执行一次,相当于是一个双保险。

js 复制代码
// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttlePlus(fn, interval) {
  // last为上一次触发回调的时间, timer是定时器
  let last = 0, timer = null
  // 将throttle处理结果当作函数返回
  return function () { 
    // 记录本次触发回调的时间
    let now = +new Date()
    // 节流
    if (now - last >= interval) {
      // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
      last = now
      fn.apply(this, arguments)
    } else {
      // 防抖
      // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
      clearTimeout(timer)
      timer = setTimeout(function () {
        last = now
        fn.apply(this, arguments)
      }, interval)
    }
  }
}

// 用新的throttle包装scroll的回调
const better_scroll = throttlePlus(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)

码上掘金

这是一个点击按钮,按钮的数字会加一的例子,分别使用了节流、防抖、杂交版节流三种方式,让你可以体验一下这三种场景。

相关推荐
优选资讯2 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
一个风轻云淡2 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u0111026753 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说4 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa4 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端
deli0074 小时前
DLA 枝晶生长实测:5000 个粒子集体停摆之后,分形维数收敛到 1.70
前端
IT_陈寒4 小时前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端
可乐鸡翅yeah_5 小时前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
程序猿追5 小时前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos
沐沐师5 小时前
Mybatis 框架教程
前端