Skip to Content
Welcome to yujie-code-blogs build by Nextra 4.0 🎉
JavaScript节流防抖

节流:在规定时间段内只执行一次

防抖:在执行函数时候,在一定时间后再触发回调函数,如果函数再次执行,则重新计时

目的是为了优化高频事件导致浏览器崩溃,并且降低 CPU 和内存的消耗,减轻服务器请求的压力,并且优化用户体验

实现原理

节流 throttle

  1. 设定一个固定的时间间隔 delay
  2. 记录上次触发的时间
  3. 每次事件触发,检查当前时间
  4. 如果当前时间-上次时间>=delay 的时间戳,则执行回调

实现:

function throttle(func, delay) { let lastTime = 0; return function (...args) { const context = this; const nowTime = Date.now(); if (nowTime - lastTime >= delay) { lastTime = nowTime; func().apply(context, [...args]); } }; } window.addEventListener( "scroll", throttle(() => { // 需要节流控制的触发事件 console.log("需要节流的事件触发"); }, 2000) );

防抖 debounce

  1. 也需要设定一个延迟时间 delay
  2. 然后创建一个延时执行变量 let timer= null;
  3. 先判断是否存在 timer,如果存在说明上一个 timer 还没执行并销毁,则先销毁 timer 指向的定时器,将 timer = null;
  4. 然后重新创建一个新的延时为 delay ,执行事件为传入需要延时执行的方法的定时器

实现:

function debounce(func,delay){ let timer = null; return function(...args){ // 由于setTimeout里面this会指向setTimeout返回的对象, // 所以这里使用context保存一下当前匿名函数的this指向 const context = this; if(timer) clearTimeout(timer); timer = setTimeout(()=>{ func.apply(context,args); },delay); }; } // 调用 document.getElementById("myinput").addEventListener( "input", debounce((e) => { console.log("输入停止:", e.target.value); }, 500) );

对比

节流:

  • 固定频率执行
  • 至少保证一定时间内一定要执行一次
  • 场景:适合高频响应的事件
    • 滚定加载 scroll
    • 搜索框实时建议(输入频率很高,但需要周期检查),例子:百度搜索栏下面弹出的建议
    • 监听浏览器窗口变化(resize)
    • 游戏中的射击按钮

防抖:

  • 事件停止后执行
  • 保证一段空闲时间后才执行一次
  • 场景:需要在事件停止一段时间后再执行操作的场景
    • 搜索框输入:用户停止输入再获取值
    • 窗口大小修改:窗口停止拖动再渲染
    • 拖拽事件 dragend