1. 什么是防抖和节流?有什么区别?如何实现?以及使用场景?
-
防抖:
就是单位时间内频繁触发事件,只执行最后一次
使用场景:搜索框搜索输入。只需用户最后一次输入完成,再发送请求。手机号,邮箱验证输入检测。
实现一:使用lodash库实现
_.debounce(fun, [wait=0], [options=])
实现二:手写防抖函数
核心思路:防抖的核心就是利用定时器来实现(setTimeout)
-
声明一个定时器变量
-
当鼠标每次滑动(事件触发)都先判断是否有定时器了,如果有定时器先清除以前的定时器。
-
如果没有定时器则开启定时器,记得存到变量里面
-
在定时器里调用要执行的函数
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)
-
声明一个定时器变量
-
当鼠标每次滑动都先判断是否有定时器存在,如果有定时器则不开始新的定时器
-
如果没有定时器则开启定时器,记得存到变量里面
定时器里面调用执行的函数定时器里面要把定时器清空
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
让异步代码看起来像同步代码,但实际上仍然是异步执行。- 使用
async
和await
可以简化异步代码的编写,提高代码的可读性和可维护性。
4. JS 异步解决方案的发展历程以及优缺点
-
回调函数
- 优点:解决了同步的问题(整体任务执行时长);
- 缺点:会产生回调地狱问题,代码难以维护,错误处理不直观,无法使用
try...catch
进行错误捕获;
-
Promise
- 优点:解决了回调地狱问题,提供了链式调用的能力,可以用
try...catch
捕获错误;
- 优点:解决了回调地狱问题,提供了链式调用的能力,可以用
-
Generator函数
- 优点:提供了控制函数执行流程的能力;可以用于实现复杂的异步逻辑;
-
Async/await
- 优点:代码清晰,不用像
Promise
写一大堆then
的链式调用,处理了回调地狱的问题; - 缺点:依赖于现代浏览器的支持,且
await
将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用await
会导致性能上的降低;
- 优点:代码清晰,不用像