Please enable Javascript to view the contents

优化递归方法的思考

 ·  ☕ 2 分钟

递归的问题

js 中的递归操作会在执行栈中不断压入函数执行栈,再不断弹出函数执行栈

在实际的执行环境中,无论是浏览器还是 Node.js 都有最大栈数的限制,一不注意就会爆栈(在之前的《js 实现深拷贝》一文中我们就遇到过爆栈的问题)

另外如果递归很深,也容易造成执行时间过长的问题

降低压栈次数的办法

  1. 尾递归优化(传入上一次计算的结果,所以不需要出栈去整合计算了,那就自然也不需要压栈了,不再需要栈)
    然而 js 没有尾递归优化,它还是会做压栈的操作…啊…这

    使用循环来代替递归,把所有的结果记录到一个数组之类的变量里,可以达到类似尾递归的操作

  2. 记忆化

    搞一个 HashMap 来记录每一次的计算结果,如果之后要计算的值之前已经算过了,就直接去 HashMap 里取结果
    这样可以减少递归中的重复计算(减少了压栈出栈次数)


React 利用记忆化优化渲染

React.memo 就使用了记忆化的办法来减少计算
如果一个组件(在 react hooks 看来组件也是一个函数)因为一些和它本身无关的变量导致刷新了(重复计算)
可以用 memo 去包裹它
这样包裹了之后,如果这个函数组件输入的参数没有变,那么每次就取缓存的结果,不用重新计算了

如果一个函数组件的某个参数是一个函数 handle,这个函数 handle 会随着 app 刷新也每次重新执行重新生成,
这样就算函数组件已经被 useMemo 包裹了,还是会重新渲染(计算),因为对他来说参数中的函数 handle 变了(每次 app 重新渲染都会生成一个新的函数 handle)
可以用 useCallBack 去渲染这个 函数 handle

猜测在 react 内部有一个用于记忆化的 HashMap,只要一个函数的输入参数不变,就会去 HashMap 里取这些参数对应的已经生成过的函数

分享

Llane00
作者
Llane00
Web Developer