今天复习了函数组合、记忆化、setTimeout 和 setInterval,以下是知识点梳理与问答整理。
一、函数组合(Compose / Pipe)
1. 什么是函数组合?
我的回答:
- 把上一个函数的返回值作为下一个函数的参数,形成流水线式的处理。
- compose 从右向左执行,pipe 从左向右执行。
补充:
-
compose (从右到左):
javascriptconst compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x) -
pipe (从左到右):
javascriptconst pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x)
2. 函数组合对函数参数有什么要求?
我的回答:
- 函数组合的参数只能有一个,如果某个函数有多个参数,需要先用柯里化转换成单参形式,再进行组合。
3. 应用场景
函数组合常用于数据流处理,比如:
-
数据清洗:trim -> toLowerCase -> replace
javascriptconst trim = s => s.trim() const toLowerCase = s => s.toLowerCase() const cleanSymbol = s => s.replace(/[@#$%]/g, '') // 组合:从左到右清洗 const cleanString = pipe(trim, toLowerCase, cleanSymbol) cleanString(' @HelloWorld# ') // 依次执行: // 1. trim -> '@HelloWorld#' // 2. toLowerCase -> '@helloworld#' // 3. replace -> 'helloworld' -
React 的高阶组件组合
javascriptconst withRouter = Component => { ... } const withRedux = Component => { ... } const withTheme = Component => { ... } // 组合多个 HOC const enhance = compose(withRouter, withRedux, withTheme) export default enhance(MyComponent)**执行顺序:**withTheme → withRedux → withRouter → MyComponent
-
Redux 中间件组合
二、记忆化(Memoization)
1. 什么是记忆化?
- 给函数加缓存,相同参数直接取缓存,避免重复计算。适用于纯函数,能有效提高性能。
2. 手写记忆化函数
我的回答:
-
用 Map 存储,根据参数生成唯一 key,存在则返回缓存值,否则计算结果并存入。
javascriptfunction memoize(fn) { const cache = new Map(); return function(...args) { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); const result = fn(...args); cache.set(key, result); return result; }; }
3. 缓存用什么数据结构?为什么?
我的回答:
- 用 Map,因为它的键可以是任意类型,而 Object 的键只能是字符串。
4. React 中的 useCallback 和 useMemo 与记忆化的关系
我的回答:
- useCallback 缓存函数本身,防止每次渲染重新创建函数;useMemo 缓存计算结果。在网易云项目中,SongItem 的点击事件可以用 useCallback 缓存。
5. 记忆化有什么限制?
我的回答:
- 只能用在纯函数上。如果函数有副作用,或相同参数可能返回不同结果,缓存会导致错误。
三、setTimeout 与 setInterval
1. 两者区别及应用场景
我的回答:
- setTimeout 指定时间后执行一次;setInterval 每隔指定时间重复执行。
- setTimeout 适合防抖、节流;setInterval 适合轮播图、计时器等周期性任务。
补充:
- 还需注意 setInterval 可能因为任务执行时间过长导致堆积,或因为回调耗时造成间隔不准。
2. 定时器在事件循环中的执行机制
我的回答:
-
定时器回调属于宏任务,必须等同步代码和微任务执行完毕后才执行。
-
即使时间到了,也要排队。浏览器最小延迟为 4ms(多次嵌套后)。
补充:
- 需注意:setTimeout 的第二个参数是最小延迟时间,而非精确执行时间。若主线程阻塞,实际延迟会更长。
3. 定时器不准时的原因
我的回答:
-
因为 JS 是单线程,如果前一个宏任务执行时间过长,定时器回调会被延迟。
-
例如
setTimeout(fn, 100),但当前代码执行了 200ms,则 fn 会在 200ms 后执行。 -
此外,浏览器对 setInterval 也有"丢帧"机制:若回调耗时超过间隔,下一次回调会立即执行,可能导致连续执行,但不堆积。
4. 如何清除定时器?不清除会导致什么问题?
我的回答:
- 用 clearTimeout(id) 或 clearInterval(id) 清除。
- 不清除可能导致内存泄漏,尤其是 setInterval 会持续执行,消耗资源,且可能操作已销毁的组件。
补充:
- 在 React 中,应在 useEffect 的清理函数中清除定时器,避免组件卸载后仍执行。