记忆化通过缓存函数结果避免重复计算,适用于纯函数、高成本、频繁调用且参数重复的场景,需注意键生成、内存消耗和缓存失效等问题,可使用Lodash的_.memoize等工具简化实现。

JavaScript中的记忆化(Memoization)是一种优化技术,它通过缓存昂贵函数调用的结果,并在相同的输入再次出现时返回缓存的结果,从而避免重复计算。本质上,它是用空间换时间,尤其适用于那些计算成本高、且纯粹(即给定相同输入总是返回相同输出)的函数。
实现记忆化函数的核心思想是创建一个高阶函数(或称为装饰器),它接受一个原始函数作为参数,并返回一个新的函数。这个新函数会在内部维护一个缓存(通常是一个Map或对象),用来存储输入参数和对应的计算结果。
一个基础的记忆化实现可能看起来像这样:
function memoize(func) {
const cache = new Map(); // 使用Map来存储参数和结果
return function(...args) {
// 简单地将所有参数拼接成一个字符串作为缓存的key
// 这对于原始类型参数是可行的,但对对象或数组有局限性
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log(`从缓存中获取结果 for key: ${key}`);
return cache.get(key);
}
console.log(`计算结果 for key: ${key}`);
const result = func.apply(this, args); // 调用原始函数
cache.set(key, result); // 存储结果
return result;
};
}
// 示例:一个计算成本较高的斐波那契数列函数
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFibonacci = memoize(fibonacci);
console.log(memoizedFibonacci(10)); // 第一次计算,并缓存
console.log(memoizedFibonacci(10)); // 第二次调用相同参数,从缓存获取
console.log(memoizedFibonacci(5)); // 第一次计算,并缓存
console.log(memoizedFibonacci(5)); // 从缓存获取这个基础实现用
JSON.stringify
JSON.stringify
立即学习“Java免费学习笔记(深入)”;
记忆化并非万能药,它有其最适合的“用武之地”。我个人认为,它最能发光发热的场景主要集中在以下几类:
举个例子,我在处理一些前端数据可视化项目时,经常会遇到需要对原始数据进行复杂聚合或转换的场景。这些转换操作往往是纯粹的,但计算量不小。如果用户频繁切换筛选条件,但很多筛选组合又会产生相同的中间数据,这时候引入记忆化就能让界面响应速度快很多,用户体验自然就好。
动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包
508
在享受记忆化带来的性能提升时,我们也不能忽视它可能引入的问题。我在实际应用中,尤其关注以下几点:
JSON.stringify
我曾经遇到过一个情况,团队为了优化一个渲染组件的数据处理,对一个函数进行了记忆化。但后来发现,这个函数接收的参数里包含了一些每次渲染都会重新创建的对象实例,即使它们的内容完全一样,
JSON.stringify
JSON.stringify
当然有,JavaScript社区非常活跃,很多常见的优化模式都有成熟的库支持。对于记忆化,最广为人知且广泛使用的工具之一就是 Lodash 库中的 _.memoize
_.memoize
import _ from 'lodash'; // 或者通过CDN引入
// 示例:一个计算成本较高的函数
function expensiveCalculation(a, b) {
console.log(`正在进行昂贵计算: ${a} + ${b}`);
// 模拟耗时操作
let sum = 0;
for (let i = 0; i < 10000000; i++) {
sum += Math.random();
}
return a + b + Math.floor(sum / 1000000); // 加上一个随机数,模拟计算结果的复杂性
}
const memoizedCalculation = _.memoize(expensiveCalculation);
console.log(memoizedCalculation(1, 2)); // 第一次计算
console.log(memoizedCalculation(1, 2)); // 从缓存获取
console.log(memoizedCalculation(3, 4)); // 第一次计算
console.log(memoizedCalculation(3, 4)); // 从缓存获取
// _.memoize 还可以接受一个 resolver 函数作为第二个参数
// 这个 resolver 函数用于自定义生成缓存键的逻辑
function customKeyResolver(a, b) {
// 例如,我们只关心第一个参数,或者将两个参数拼接起来
return `${a}_${b}`;
}
const memoizedWithCustomKey = _.memoize(expensiveCalculation, customKeyResolver);
console.log(memoizedWithCustomKey(10, 20)); // 第一次计算
console.log(memoizedWithCustomKey(10, 20)); // 从缓存获取
console.log(memoizedWithCustomKey(20, 10)); // 第一次计算 (因为key是"20_10")_.memoize
resolver
JSON.stringify
除了Lodash,还有一些其他专注于记忆化的库,比如
reselect
_.memoize
以上就是如何实现JavaScript中的记忆化函数?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号