🤌🤌🤌一文轻松拿捏防抖和节流

257 阅读4分钟

前言

听说你还不会前端面试中常考的“防抖”和“节流”?其实并没有那么难,下边我先用一个大家日常游戏 Timi 王者荣耀中的两个情况“回城”和“施法”,其中防抖就是回城,而节流就是施法。

image.png

大家可能没Get到我们先学习一下,回过头大家就轻松拿捏了!

防抖

防抖 ,即确保某个函数在一段时间内之执行一次,但执行函数之后等待规定的时间内没有触发才会执行当前函数。

手搓一个防抖函数:

function debounce(fn,delay){
	let timer;
	return function(){
		const _this = this;
		const args = arguments;
		if(timer){
			clearTimeout(timer);
		}
		timer = setTimeout(()=>{
			fn.apply(context, args);
		},delay)
	}
}
  • 先创建一个定时器变量timer
  • 每次时间触发先判断是否存在定时器,若有则清楚之前的定时器;
  • 若没有定时器,则新建定时器并存入到定时器变量中;
  • 定时器时间到,执行回到运行fn函数;

手搓一个防抖函数,可通过immediate判断是否立即执行:

  // immediate为true时为立即执行,false为非立即执行
  function debounce(func, wait, immediate) {
    let timer;
    return function () {
      const _this = this;
      const args = arguments;
      if (timer) clearTimeout(timer);
      if (immediate) {
        const callNow = !timer;
        timer = setTimeout(() => {
          timer = null;
        }, wait)
        if (callNow) func.apply(_this, args)
      }
      else {
        timer = setTimeout(() => {
          func.apply(context, args)
        }, wait);
      }
    }
  }
特性非立即执行立即执行
首次触发不立即执行,等 delay 后执行立即执行
适用场景用户输入完成后执行(如搜索框、表单验证)用户点击、首次操作时需要立即响应(如按钮点击)
资源消耗减少高频操作的资源消耗适合需要立即响应的操作,如按钮防抖、API 请求
用户体验更适合不需要立刻反应的场景用户点击时,立即给予反馈,更直观的响应

使用场景:

  1. 电梯开门:电梯门在有人进出时会不断触发关闭倒计时,但只有在最后一次有人进入后的一段时间内无人再进出,电梯门才会真正关闭;
  2. 输入搜索:在搜索框输入内容时,用户每次输入都会触发搜索请求,但搜索请求应该在用户停止输入一段时间后再执行,避免频繁请求服务器。

节流

节流 ,即某个函数在短时间内多次触发,会按照固定的时间间隔执行,而不会让他高频触发。

手搓一个节流函数:

// 定时器版本
function throttle(func,wait){
	let timer;
	return function (){
		const _this = this; 
		const args = arguments;
		if(!timer){
			timer = setTimeopunt(()=>{
				fn.apply(_this, args); 
				timer = null;
			},wait)
		}
	}
}

// 时间戳版本
function throttleWithTimestamp(fn, delay) {
  let lastTime = 0;
  return function () {
	const _this = this; 
	const args = arguments;
    const now = Date.now();
    if (now - lastTime >= delay) {
      fn.apply(_this, args); // 立即执行
      lastTime = now;
    }
  };
}

  • 先创建一个定时器变量timer
  • 事件触发都要判断是否存在定时器,若存在则不开启新的定时器;
  • 若没有新的定时器,则开始定时器并存至timer变量中;
  • 时间到,执行定时器回调,即执行func函数并清空timer;
版本触发时机适用场景
时间戳版立即执行,之后 delay 时间内不执行鼠标移动、滚动事件(想要第一下生效)
定时器版不立即执行delay 后执行防止高频触发但不丢失最后一次执行

使用场景

  1. 公交车发车:即使乘客不断到达,公交车也会按照固定的时间间隔发车,而不会每到一个人就立刻发车;
  2. MOBA 游戏技能:即技能冷却之时不能进行技能的施放,当技能冷却转好之后才可以进行技能的释放。

总结

防抖和节流是相关的,它们都能提高网页的性能。只是它们应用于不同的情况:

  1. 防抖(Debounce)只关心最终状态:当事件频繁触发时,只有最后一次触发后 delay 毫秒才执行,适用于需要最终结果的场景(如搜索框输入、表单验证)。
  2. 节流(Throttle)关心中间状态:以固定速率执行事件处理,适用于需要频繁处理但限制执行频率的场景(如滚动监听、窗口调整)。

上述时小弟的一点点理解,希望能一次积累进步,若存在错误请指出,谢谢大家!!!


学习参考:
1.防抖和节流及多种实现方式
2.一杯茶的时间🍵,带你彻底学会手写防抖节流


文章荐读:

  1. 🔥🔥🔥Vite6 +TypeScript+Vue3+Tailwind+ESlint+Prettier+Husky搭建企业级前端项目
  2. 📸📸📸前端屏幕录制解决方案探索———WebRTC,html2canvas和rrweb
  3. Vite6 +TypeScript+React18+Tailwind+ESlint+Prettier+Husky搭建企业级前端项目
  4. 🧠🧠🧠由一个BUG引发的对JavaScript运行机制Event Loop的探索