一、先给面试官的“标准定义”(先声夺人)
防抖(debounce):在事件触发一段时间后才执行,期间再次触发会重新计时
节流(throttle):在固定时间内只执行一次
这一句一定要先说。
二、为什么在 React Hooks 里要“特别处理”?
问题本质:闭包 + 重新渲染
const fn = () => { console.log(count) }每次 render 都是新函数
定时器 / 事件里用的可能是旧状态
👉普通 JS 防抖在 Hooks 里会失效或拿到旧值
三、Hooks 防抖(推荐实现)
1️⃣ 最稳方案:useRef + useCallback
function useDebounceFn(fn, delay = 300) { const timer = useRef<number | null>(null) const fnRef = useRef(fn) // 始终指向最新 fn,解决闭包问题 fnRef.current = fn const debounce = useCallback((...args) => { if (timer.current) { clearTimeout(timer.current) } timer.current = window.setTimeout(() => { fnRef.current(...args) }, delay) }, [delay]) return debounce }使用方式
const onSearch = useDebounceFn(value => { fetchList(value) }, 500) <input onChange={e => onSearch(e.target.value)} />2️⃣ 面试官加分点
使用 useRef 保存最新函数,避免闭包导致状态不更新。
四、Hooks 节流(两种方式都要会)
方案一:时间戳节流(最稳定)
function useThrottleFn(fn, delay = 300) { const lastTime = useRef(0) const fnRef = useRef(fn) fnRef.current = fn return useCallback((...args) => { const now = Date.now() if (now - lastTime.current >= delay) { lastTime.current = now fnRef.current(...args) } }, [delay]) }方案二:定时器节流(常被追问)
function useThrottleFn(fn, delay = 300) { const timer = useRef<number | null>(null) const fnRef = useRef(fn) fnRef.current = fn return useCallback((...args) => { if (timer.current) return timer.current = window.setTimeout(() => { fnRef.current(...args) timer.current = null }, delay) }, [delay]) }两种节流的区别(面试官爱问)
| 方式 | 特点 |
|---|---|
| 时间戳 | 立即执行 |
| 定时器 | 延迟执行 |
五、为什么不用 lodash debounce?
可以用,但要说清楚限制
const debouncedFn = useMemo( () => debounce(fn, 300), [] )❌ 问题:
fn 变了,debounce 不更新
容易产生脏数据
正确用法
const fnRef = useRef(fn) fnRef.current = fn const debounced = useMemo( () => debounce((...args) => fnRef.current(...args), 300), [] )六、Hooks 防抖节流常见坑(必背)
❌ 错误写法
const fn = debounce(() => { setCount(count + 1) }, 300)问题
每次 render 都创建新 debounce
count 永远是旧值
✅ 正确认知
防抖节流函数要只创建一次
执行的函数要始终是最新的
七、什么时候用防抖?什么时候用节流?
防抖(Debounce)
搜索框
输入联想
表单校验
节流(Throttle)
滚动
resize
拖拽
八、面试终极总结(一定要背)
React Hooks 下实现防抖节流,关键不是 setTimeout,而是用 useRef 解决闭包问题,保证函数引用稳定且状态最新。