JavaScript中Memoize函数写法是否正确?求正确实现方案
你的JavaScript Memoize函数写法问题及修正方案
你的代码能实现基础的缓存效果,但存在几个关键问题,导致它在很多场景下无法正常工作:
- 缓存key生成逻辑有缺陷:用
a+""+b拼接字符串会导致参数组合冲突,比如memo(12, 3)和memo(1, 23)会生成相同的key"123",缓存结果会相互覆盖。 - 与sum函数强耦合:memo函数只能为sum服务,无法复用给其他函数,通用性极差。
- 全局缓存污染:
cache是全局变量,若其他代码也使用同名变量或缓存逻辑,会互相干扰。 - 假值缓存失效:如果sum返回0、false等假值,
if(cache[key])会判断为假,导致重复计算,无法正确缓存这些结果。
正确的通用Memoize实现
function memoize(fn) { // 用闭包存储缓存,避免全局污染 const cache = new Map(); return function(...args) { // 序列化参数生成唯一key,支持多参数、基础类型参数 const key = JSON.stringify(args); // 直接判断key是否存在,而非值是否为真 if (cache.has(key)) { return cache.get(key); } const result = fn.apply(this, args); cache.set(key, result); return result; }; } // 使用示例 function sum(a, b) { console.log(`Entering sum function ${a} & ${b}`); return a + b; } // 生成带缓存的sum函数 const memoizedSum = memoize(sum); console.log(memoizedSum(1, 2)); console.log(memoizedSum(3, 2)); console.log(memoizedSum(3, 2)); // 直接返回缓存,不调用sum console.log(memoizedSum(1, 2)); // 直接返回缓存,不调用sum console.log(memoizedSum(5, 2));
补充说明
- 这个实现是通用的,能给任意函数添加缓存能力,比如
const memoizedPow = memoize(Math.pow)就能得到带缓存的幂运算函数。 - 使用
Map存储缓存,判断key是否存在的逻辑更可靠,避免了假值导致的缓存失效问题。 - 若需要处理函数、Symbol等无法序列化的参数,可以自定义key生成逻辑(比如针对对象参数使用
WeakMap),适配特定场景需求。
内容的提问来源于stack exchange,提问作者Pavithran Baskaran
相关产品推荐
相关产品推荐

