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