记忆函数—前端显著提高性能和响应速度的神器

往期回顾

超简单的原生Hmtl实现元素拖拽交换顺序

ES6常用十大特性详解

vue中给v-for循环生成的元素批量设置ref的方法

Vue实现高自由度的自定义拖拽指令

记忆函数

JavaScript 中的记忆函数(Memoization)是一种优化技术,用于提高函数的效率。它的基本思想是存储昂贵的函数调用结果,当再次以相同的参数调用该函数时,可以直接返回存储的结果,避免不必要的计算。

在 JavaScript 中,记忆函数通常通过闭包来实现。闭包可以访问其词法作用域,即使函数在其词法作用域之外执行。这意味着,闭包可以记住并访问创建它时作用域中的变量。利用这个特性,我们可以创建一个函数,它记住了为给定参数执行原始函数的结果。

下面是一个简单的记忆函数的实现:

function memoize(func) {
  let cache = {};

  return function(...args) {
    // 将参数转换为字符串,作为缓存的键
    const key = JSON.stringify(args);

    // 如果结果已经在缓存中,则直接返回缓存的结果
    if (cache[key]) {
      return cache[key];
    }

    // 否则,调用原始函数,并将结果存储在缓存中
    const result = func.apply(this, args);
    cache[key] = result;

    return result;
  };
}

使用时,只需将要记忆化的函数作为参数传递给 memoize 函数。例如:

function expensiveComputation(num) {
  // 模拟一个耗时的计算
  console.log(`计算 ${num}`);
  return num * num;
}

const memoizedFunction = memoize(expensiveComputation);

memoizedFunction(4); // 计算并缓存结果
memoizedFunction(4); // 直接返回缓存的结果,不进行计算

在上述示例中,首次调用 memoizedFunction(4) 时,会进行计算并缓存结果。当再次以相同的参数调用 memoizedFunction(4) 时,由于结果已经在缓存中,函数将直接返回缓存的结果,而不会进行重复的计算。

记忆函数在处理大量数据或频繁调用函数的情况下非常有用,例如在处理大型数据集、频繁的API调用或复杂的算法时。通过记忆化,可以显著提高应用程序的性能和响应速度。

闭包

JavaScript 中的闭包是一个非常强大且核心的特性,它允许函数记住并访问其词法作用域,即使函数在其词法作用域之外执行。闭包可以让你保存状态——即,它们可以记住并访问创建它们时作用域中的变量,上面的记忆函数就是靠闭包实现的。下面通过一些例子来详细解释闭包的概念。

闭包的基本例子

function createCounter() {
  let count = 0;
  return function() {
    // 这里的匿名函数就是闭包,它能够访问上层函数作用域中的变量count
    count += 1;
    return count;
  };
}

const counter = createCounter(); // 调用createCounter时,会创建一个闭包
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

在这个例子中,createCounter 函数返回了一个匿名函数,这个匿名函数可以访问并修改外部函数 createCounter 的局部变量 count。即使 createCounter 的执行上下文已经消失,返回的函数仍然可以访问 count 变量,这是因为闭包。

当调用 createCounter() 时,JavaScript 会为 createCounter 创建一个执行上下文,在这个上下文中,let count = 0; 被执行一次,创建一个 count 变量,并将其初始值设置为 0。然后,createCounter 函数返回一个匿名函数,这个匿名函数就是一个闭包,它能够访问 createCounter 函数作用域中的 count 变量。

当调用 counter() 时,实际上是调用了 createCounter 返回的那个匿名函数。这个匿名函数执行时,它的执行上下文是 createCounter 的执行上下文,因此它能够访问 createCounter 作用域中的 count 变量。每次调用 counter() 时,都会访问同一个 count 变量,因此 count 的值会在每次调用之间共享。

闭包的持久性

闭包的持久性意味着闭包中的变量会一直保持在内存中,这既是闭包的优势也是它的缺点(可能导致内存泄漏)。

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

const add5 = makeAdder(5);
console.log(add5(10)); // 输出:15

// 即使makeAdder的执行上下文已经消失,x仍然被保留在内存中

总结

记忆函数和闭包是 JavaScript 中非常强大和实用的特性。记忆函数通过闭包实现,可以避免重复计算,提高程序的性能和响应速度,尤其在处理大量数据或频繁调用函数的情况下非常有用。闭包则可以让函数记住并访问其词法作用域,即使函数在其词法作用域之外执行,这一特性为 JavaScript 的函数编程提供了极大的灵活性和表达能力。理解和掌握这两个概念,对于深入学习和应用 JavaScript 来说非常重要。

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马可家的菠萝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值