这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战 | 创作学习持续成长,夺宝闯关赢大奖
解析30 seconds of code网站代码片段之「可缓存的函数」
可缓存的函数
const memoize = (fn) => {
const cache = new Map();
const cached = function (val) {
return cache.has(val)
? cache.get(val)
: cache.set(val, fn.call(this, val)) && cache.get(val);
};
cached.cache = cache;
return cached;
};
// 举例
const cachedFunc = memoize(testFun);
testFun(param); // 运行即缓存
testFun(param); //第二次的结果会快于第一次
流程解析
- 通过新建空的
map
来缓存函数结果,通过属性的形式挂载在返回出去的cached
函数上来保证后续cache
能被获取。 memorize
函数返回一个可缓存的cached
函数,然后通过传参时map
判断是否缓存来返回最终结果。如果已缓存就直接返回缓存结果,如果未缓存就运行函数并且缓存结果。
技术解析
memoization主要是使用缓存来存储结果,以便后续调用耗时的函数不会再次执行一遍函数,这样来加快代码速度。
- Memoization 应该主要用于加速性能缓慢、成本高或耗时的函数调用
- Memoization 可加快后续调用的速度,因此最好预计在相同情况下对同一函数进行多次调用时使用
- Memoization 将结果存储在内存中,因此在非常不同的情况下多次调用同一函数时就最好别缓存,不然会给内存造成负担
vue
中的computed
就是通过map
缓存来实现的。
thinking
memoize
函数的实现其实比较简单,利用ES6的新特性map方法很轻松就实现了,所以这里的思考主要是想说这个函数不能随便乱用。缓存数据加快函数的运算速度听起来挺好,但是对于需要频繁计算/函数入参频繁变化的函数,会使得map在内存中的体积快速加大,内存负担就会导致运算速度下降。
目前,我自己遇到一个使用场景:用户在编辑器类编辑的文章,需要分析文章的DOM结构得到结构化参数,这个分析行为可以抽象为一个函数。分析一次DOM结构是比较耗时的,我翻了翻项目里至少有三个场景需要用到这个函数的结果,原来的写法就是相同的入参(文章的DOM结构是不变的)这个函数在不同地方调用了三次,未来可能更多。此时,就需要缓存函数将第一次分析的结果缓存了,之后再调用就可以直接使用缓存的结果。
所以我使用这个对项目代码进行了一个小改造,也算是一个小的性能提升。