直接用闭包加缓存对象可实现高性能轻量记忆函数:闭包封装隔离缓存、参数键需稳定高效(避免json.stringify隐患)、轻量场景无需过期机制,一行代码即可复用。

直接用闭包 + 缓存对象就能实现高性能的轻量记忆函数,不需要引入第三方库,关键在于参数键生成合理、缓存生命周期可控、不污染原始逻辑。
用闭包封装缓存,避免全局污染
记忆函数的核心是把缓存数据藏在函数作用域内,外部无法直接访问或误改。闭包天然提供这个隔离能力:
- 每次调用 memoize(fn) 都会创建独立的 cache 对象,不同函数互不影响
- 缓存对象不暴露在外,不会被意外清空或覆盖
- 适合组件级或工具函数级复用,比如一个表格组件里多个字段用到相同格式化逻辑
参数转键要稳定且高效
缓存是否命中,取决于参数能否生成唯一、可复用的键。JSON.stringify 虽简单但有隐患:
- 对象属性顺序不同会导致键不同(
{a:1,b:2}和{b:2,a:1}生成不同键) - 函数、undefined、Symbol 会丢失或报错
- 大数据量时序列化本身有开销
更稳妥的做法是:基础类型直接拼接,简单对象按 key 排序后字符串化,忽略不可序列化值:
例如:const key = Array.isArray(args) ? args.join('|') : String(args);
轻量场景下无需过期或淘汰机制
如果只是做前端本地计算缓存(如坐标转换、字符串截断、单位换算),通常满足三个特点:输入有限、结果不变、内存压力小。这时可以省略 TTL 和 LRU:
- 缓存一直有效,直到页面刷新或组件卸载
- 避免增加判断逻辑,保持函数体简洁
- 真正需要时效性的场景(如用户权限校验),应走 API 层缓存,而非记忆函数
实战写法:一行可复用的记忆包装器
下面这个版本兼顾可读性、兼容性和性能,适用于大多数轻量计算:
const memoize = (fn) => { const cache = {}; return (...args) => { const key = args.map(a => typeof a === 'object' && a !== null ? JSON.stringify(a) : String(a)).join('|'); if (key in cache) return cache[key]; const result = fn(...args); cache[key] = result; return result; }; };
- 支持多参数、混合类型(数字、字符串、简单对象)
- 对 null/undefined/Date 等特殊值做了保底处理
- 调用时完全透明:
const fastFib = memoize(fib); fastFib(30);
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











