第11天:函数组合、记忆化与定时器

今天复习了函数组合、记忆化、setTimeout 和 setInterval,以下是知识点梳理与问答整理。


一、函数组合(Compose / Pipe)

1. 什么是函数组合?

我的回答:

  • 把上一个函数的返回值作为下一个函数的参数,形成流水线式的处理。
  • compose 从右向左执行,pipe 从左向右执行。

补充:

  • compose (从右到左)

    javascript 复制代码
    const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x)
  • pipe (从左到右):

    javascript 复制代码
    const pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x)

2. 函数组合对函数参数有什么要求?

我的回答:

  • 函数组合的参数只能有一个,如果某个函数有多个参数,需要先用柯里化转换成单参形式,再进行组合。

3. 应用场景

函数组合常用于数据流处理,比如:

  • 数据清洗:trim -> toLowerCase -> replace

    javascript 复制代码
    const 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 的高阶组件组合

    javascript 复制代码
    const 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,存在则返回缓存值,否则计算结果并存入。

    javascript 复制代码
    function 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 的清理函数中清除定时器,避免组件卸载后仍执行。
相关推荐
小江的记录本2 小时前
【Docker】《 Docker 高频常用命令速查表 》
java·前端·后端·http·docker·容器·eureka
Beginner x_u2 小时前
前端八股整理|Vue|虚拟 DOM、Diff 与 Patch 流程
前端·javascript·vue.js
kaixiang3002 小时前
若依RuoYi实战
java·服务器·前端
今天又在摸鱼2 小时前
py工程+爬虫
开发语言·python
j_xxx404_2 小时前
【创作一周年纪念】365天的坚持:从《初识C语言》到现在的成长之旅,感谢遇见
c语言·开发语言·ai写作·节日
李松桃2 小时前
Python爬虫-第一课
开发语言·python
NocoBase2 小时前
为 Excel 数据快速构建 Web 应用:4 种方法对比
前端·人工智能·低代码·开源·excel
在放️2 小时前
Python 爬虫 · 理论基础
开发语言·爬虫·python
kyle~2 小时前
C++---Boost库(准标准库)
开发语言·c++·机器人·ros·boost