JS调用memoize记忆化函数返回函数而非计算结果的问题
问题原因
getMaxValue的定义写法错误:当前写法const getMaxValue = (config) => memoize(_getMaxValue)是一个接收config参数、每次调用都会返回新的memoize包装函数的普通函数,调用getMaxValue(config)时根本没有执行包装后的计算逻辑,直接返回了memoize生成的内部闭包函数,因此打印结果是函数块。对比正常工作的add可以发现差异:add是直接执行memoize(_add)拿到包装后的计算函数,调用时传参就会触发计算,这才是memoize的正确用法。- 现有memoize实现逻辑不通用:内部硬编码了
args.reduce((acc, curr) => fn(acc, curr), 0)的调用逻辑,仅适配累加类多参数函数,完全不支持_getMaxValue这类单参数、不需要归约计算的函数。就算修正了getMaxValue的定义,这段逻辑也会把初始值0作为第一个参数传入原函数,导致入参不符合预期,计算结果错误。
修正后代码
const config = { 14340: 1195, 15774: 1226, 17208: 1257, 18642: 1288, 20076: 1319 } const memoize = (fn) => { let cache = {} return (...args) => { // 用JSON.stringify处理参数,避免对象类型参数生成错误缓存key let cacheKey = args.map(n => JSON.stringify(n)).join('+') if (cacheKey in cache) { return cache[cacheKey] } // 直接透传所有参数给原函数,不硬编码归约逻辑,适配任意入参形式 const result = fn.apply(this, args) cache[cacheKey] = result return result } } function _getMaxValue(config) { const keys = Object.keys(config) .map((k) => parseInt(k, 10)) .sort(); return config[keys[keys.length - 1].toString()]; } // 移除外层多余的箭头函数包装,直接赋值memoize返回的包装函数 const getMaxValue = memoize(_getMaxValue) const _add = (a, b) => { return a + b } const add = memoize(_add) console.log(getMaxValue(config)) // 输出1319,符合预期 console.log(add(1, 2)) // 输出3,正常运行
修改说明
- 移除
getMaxValue外层多余的箭头函数包装,和add的定义保持一致,调用时传入参数即可直接触发计算逻辑 - 去掉memoize内部硬编码的reduce归约逻辑,改用
fn.apply(this, args)透传所有入参,适配任意参数形式的工具方法 - 优化缓存key生成逻辑,用
JSON.stringify处理参数,避免对象、引用类型参数转字符串时出现[object Object]导致的缓存key冲突问题
内容的提问来源于stack exchange,提问作者volna
相关产品推荐
相关产品推荐

