前端面试题目系列七

1. 什么是防抖和节流?有什么区别?如何实现?以及使用场景?

  • 防抖

    就是单位时间内频繁触发事件,只执行最后一次

    使用场景:搜索框搜索输入。只需用户最后一次输入完成,再发送请求。手机号,邮箱验证输入检测。

    实现一:使用lodash库实现

    _.debounce(fun, [wait=0], [options=])

    实现二:手写防抖函数

    核心思路:防抖的核心就是利用定时器来实现(setTimeout)

    1. 声明一个定时器变量

    2. 当鼠标每次滑动(事件触发)都先判断是否有定时器了,如果有定时器先清除以前的定时器。

    3. 如果没有定时器则开启定时器,记得存到变量里面

    4. 定时器里调用要执行的函数

      const box = document.querySelector('.box')
      let i = 0
      function mouseMove() {
          box.innerHTML = i++
      }
      
      
      //手写防抖函数
      function debounce(fn, t) {
          let timer
          //return 返回一个匿名函数
          return function () {
              //2.3.4
              if(timer) clearTimeout(timer)
              timer = setTimeout(function(){
                  fn()   //加小括号调用fn()函数
              }, t)
          }
      }
      
      
      box.addEventListener('mouseover', debounce(mouseMove, 500))
      
  • 节流:

    单位时间内频繁触发事件,只执行一次

    实现一:利用lodash库实现节流

    _.throttle(func, [wait = 0], [options= ]) 创建一个节流函数,在wait秒内最多执行func一次的函数

    实现二:手写节流函数

    要求: 鼠标在盒子上移动,不管移动多少次,每隔500ms才+

    核心思路:节流的核心就是利用定时器来实现(setTimeout)

    1. 声明一个定时器变量

    2. 当鼠标每次滑动都先判断是否有定时器存在,如果有定时器则不开始新的定时器

    3. 如果没有定时器则开启定时器,记得存到变量里面
      定时器里面调用执行的函数

      定时器里面要把定时器清空

      const box = document.querySelector('.box')
      let i = 0
      
      function mouseMover(){
          box.innerHTML = i++
      }
      
      //手写节流函数
      function throttle(fn, t){
          let timer = null
          if(!timer) {
             timer =  setTimeout(function (){
                  fn()
                  timer = null     //关键的一步,清空定时器,在setTimeout中是无法删除定时器的,因为定时器还在运作,所以用timer = null,而不是clearTimeout(timer)
              }, t)
          }
      }
      
      
      box.addEventListener('mousemove', throttle(mouseMove, 500))
      

2. 什么是回调地狱以及如何解决?

回调地狱(Callback Hell),是指在 JavaScript 中,由于异步操作的嵌套调用导致代码结构变得复杂且难以维护的现象。当多个异步操作需要按顺序执行时,通常会使用回调函数来处理每个操作的结果。当这些回调函数层层嵌套时,代码就会变得难以阅读和维护。

  • 使用Promise解决,Promises 提供了 .then().catch() 方法来处理成功和失败的情况,并且可以链式调用,减少了嵌套的深度。
  • 使用Async/await方式解决,async/await 是一种让异步代码看起来像同步代码的语法糖,async 关键字用于声明一个异步函数,await 关键字用于等待一个 Promise 完成,使用 async/await 可以极大地提高代码的可读性和可维护性,因为它将异步操作写得更像同步操作。

3. Async/Await 如何通过同步的方式(形式)实现异步?

  • async/await 是一种让异步代码看起来像同步代码的语法糖,async 关键字用于声明一个异步函数,await 关键字用于等待一个 Promise 完成。
  • 使用 async 关键字定义一个函数,这样函数内部就可以使用 await,在 async 函数内部,使用 await 关键字等待一个返回 Promise 的函数。
  • 使用 try...catch 结构来处理可能发生的错误
  • async/await 让异步代码看起来像同步代码,但实际上仍然是异步执行。
  • 使用 asyncawait 可以简化异步代码的编写,提高代码的可读性和可维护性。

4. JS 异步解决方案的发展历程以及优缺点

  1. 回调函数

    • 优点:解决了同步的问题(整体任务执行时长);
    • 缺点:会产生回调地狱问题,代码难以维护,错误处理不直观,无法使用 try...catch 进行错误捕获;
  2. Promise

    • 优点:解决了回调地狱问题,提供了链式调用的能力,可以用 try...catch 捕获错误;
  3. Generator函数

    • 优点:提供了控制函数执行流程的能力;可以用于实现复杂的异步逻辑;
  4. Async/await

    • 优点:代码清晰,不用像 Promise 写一大堆 then 的链式调用,处理了回调地狱的问题;
    • 缺点:依赖于现代浏览器的支持,且await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值