面试考题:防抖和节流,你应该了解一下

80 阅读4分钟

“没状态了,找个安全的地方回城吧...”残血的蛮王这样说到。

突然远处射出几根蓝色的寒冰箭,伤害不高,侮辱性极强。

你的回城被打断了,只能找个地方重新开始回城,又要等待一段时间了。

在快结束读条的时候,又射来了几根箭,又将你的回城打断了。

此时蛮王心里想,如果寒冰再射箭,我一定拿她一血。

在蛮王第三次回城的时候,箭还是出现了。

此时蛮王气急败坏,疾跑一开,"今天不拿到你的一血,我以后不叫五秒真男人"

一根巨大的箭射出,把蛮王定在原地,蛮王疯狂的使用E技能,却只能执行第一次按下e的命令,一直被大小箭拉扯减速。

最后蛮王终于追到了艾希,开始了没羞没臊的生活

image.png

上文所写蛮王的故事里,隐藏了两个我们面试经常考的题目。

面试官:请你解释一下防抖和节流。。。

防抖

什么是防抖?

防抖(debounce)用于限制函数在短时间内被频繁调用,只有当调用停止后经过一段设定的等待时间才实际执行该函数。执行最后一次

就像上文蛮王的回城,受到伤害被打断了就要重新开始读条。

image.png

我们通过手写一个简单的代码来了解防抖:

  // 防抖
  function debounce(fn, delay) {
    let id;
    return function() {
      // 限流
      clearTimeout(id);
      id =  setTimeout(()=>{
        fn()
      },delay)
      }
      fn();
    }
  </script>
</body>
</html>

忽略了一些不重要的步骤。首先我们先创建一些我们的后端数据。以json数组方式存在。

{
  "users": [
    {
      "id": "1",
      "name": "蛮王"
    },
    {
      "id": "2",
      "name": "艾希"
    },
    {
      "id": "3",
      "name": "剑圣"
    }
  ]

运行得到结果:

image.png

要想链接数据,第一步先启动我们的json-server。完成一些操作之后再json文件终端中输入npm run dev即可启动服务。不会的可以直接使用我的代码,更换掉自己的package.json里的数据就可以了。非常的简单的方便

"scripts": {
    "dev": "json-server --watch db.json --port 3001"
  },
  
  "dependencies": {
    "json-server": "^1.0.0-beta.3"
  }

利用Dom获取节点和设置监听器

  <script>
  const oUL = document.querySelector('#users');
  // 通往后端接口
  const oInput = document.getElementById('unDebounceInput');
  // 当作为事件的处理函数来用时,this 指向事件的目标元素
  const debounceNameSearch = debounce(handleNameSearch, 5000);
  oInput.addEventListener('keyup', debounceNameSearch)

再创建一个执行函数,输入框更改时,fliter筛选出包含用户名字的信息。

function handleNameSearch() {
    let value = oInput.value.trim();
    if (value === '') {
      oUL.innerHTML = '';
      return;
    }
    fetch('http://localhost:3001/users')
      .then(res => res.json())
      .then(users => {
        const filterUsers = users.filter(
          user =>  user.name.includes(value)
        )
        oUL.innerHTML = filterUsers.map(user =>  `
          <li>
            ${user.name}
          </li>
          `
        ).join("") 
      })
  }

节流

节流又是什么呢?

节流(Throttle)是一种限制函数执行频率的技术,确保函数在指定的时间间隔内最多只执行一次,常用于控制频繁触发的事件如滚动、调整窗口大小或连续点击。

让我们继续回到蛮王和艾希的故事中好吗?当你的技能冷却好了的时候,你并不能多次使用,只能在你第一次按下技能的时候时候。

一个更生动的例子,假如你玩的是稻草人。你的大招需要一段大约3秒的引导时间,哪怕你在引导的期间疯狂的按r,也只会执行第一次。

image.png

代码和防抖大差不差,这里就不从头开始写了。

节流:

function throttle(fn, t) {
  let timer = null 
  return function () {  
    if (!timer) {   
      timer = setTimeout(() => {
        fn()  
        timer = null 
      }, 1000);
    }
  }
}

其实总的来说,节流和防抖的实现都与我们的定时器密切相关。可以看看博主的定时器文章可以看看博主的定时器文章:面试考题:定时器底层逻辑前言 ,相信你会受益匪浅的。

当然也有更简便的写法,比如用lodash,可以很大程度的节省我们需要写的代码量。

总的来说,防抖和节流就是两个可以说是相反行为的方法。一个执行最后一次,一个执行第一次。都设置定时器,防抖捕捉每次事件发生的行为,节流在执行时忽略其他事件的执行。再多加巩固,可以掌握的非常快。

  • 防抖 适用于那些只需要响应最后一次操作的场景,比如输入框内容变化、按钮点击等。
  • 节流 适用于那些需要频繁响应但不需要每次触发都处理的场景,比如滚动、调整窗口大小、鼠标移动等。

感谢各位的观看。