参数敏感型缓存需精确区分类型、引用、undefined/null/NaN及参数顺序,推荐用Map配合自定义键生成器实现;增强策略包括支持this、LRU容量控制、手动清理及纯函数校验。

用闭包实现“参数敏感型缓存”的高阶函数,核心在于:让缓存键能精确区分不同参数组合,避免因参数序列化失真导致的误命中或漏命中。这不是简单存个对象,而是围绕参数的结构、类型、顺序和语义做精准建模。
参数敏感型缓存的关键设计点
所谓“参数敏感”,是指缓存机制必须能识别以下差异:
-
值相同但类型不同:比如
1和"1"应视为两个键 -
对象内容相同但引用不同:
{a: 1}和{a: 1}默认不是同一键(除非显式深比较) -
undefined / null / NaN 的明确表达:JSON.stringify 会忽略
undefined,导致[1, undefined]和[1]生成相同 key -
参数顺序不可互换:
fn('a', 'b')和fn('b', 'a')必须对应不同结果
用 Map + 自定义键生成器实现健壮缓存
推荐弃用 JSON.stringify,改用 Map 存储,并编写轻量级键生成函数,保留原始类型信息:
// 支持多参数、类型区分、undefined 显式编码
function memoize(fn) {<br> const cache = new Map();<br> return function(...args) {<br> // 生成唯一可比键:[type, value] 元组数组<br> const key = args.map(arg => [<br> typeof arg,<br> arg === undefined ? 'UNDEFINED' :<br> arg === null ? 'NULL' :<br> arg === NaN ? 'NaN' :<br> arg<br> ]);<br> if (cache.has(key)) {<br> return cache.get(key);<br> }<br> const result = fn.apply(this, args);<br> cache.set(key, result);<br> return result;<br> };<br>}
适配实际场景的增强策略
生产环境需考虑更多边界:
-
支持 this 上下文:用
fn.call(this, ...args)替代apply,确保原函数行为一致 -
限制缓存容量:加入 LRU 逻辑,或直接使用
lru-cache库替代原生 Map -
允许手动清理:返回的函数挂载
.clear()方法,便于测试或重置状态 - 标记纯函数前提:在文档或运行时校验输入是否为纯函数(无副作用、无外部依赖),否则抛警告
一个即插即用的优化插件雏形
封装成可配置的高阶函数工厂,支持常见定制项:
function createMemoPlugin({ maxAge = 0, maxSize = 100, keyGen } = {}) {<br> return function memoize(fn) {<br> const cache = new Map();<br> const getKey = keyGen || defaultKeyGen;<br> return function(...args) {<br> const key = getKey(args);<br> const entry = cache.get(key);<br> if (entry && (!maxAge || Date.now() - entry.time < maxAge)) {<br> return entry.value;<br> }<br> const value = fn.call(this, ...args);<br> cache.set(key, { value, time: Date.now() });<br> if (cache.size > maxSize) cache.delete(cache.keys().next().value);<br> return value;<br> };<br> };<br>}
这样就能按需生成插件实例:
const fastMath = createMemoPlugin({ maxSize: 50 });<br>const memoizedFib = fastMath((n) => n <= 1 ? n : memoizedFib(n-1) + memoizedFib(n-2));

















