首页 > 其他分享 >前端记忆函数和LRU缓存

前端记忆函数和LRU缓存

时间:2024-06-04 09:04:32浏览次数:27  
标签:缓存 return 前端 cache value LRU key 键值

在Js中,“记忆化(Memoization)”是一种优化技术,它通过存储昂贵函数的结果,并复用这些结果以避免重复执行,从而可以加快代码执行速度。这种技术在处理递归和迭代问题时尤其有用。

下面是一个记忆化函数的一般实现:

function memoize(fn){
    let cache = {}
    return function(...args){
        let n = args[0]
        if ( n in cache ) {
            console.log('Fetching from cache');
            return cache[n]
        }
        else {
            console.log('Calculating result');
            let result = fn(n)
            cache[n] = result;
            return result;
        }
    }
}

// 例如: 我们有一个计算斐波那契数列的函数:
var fib = function(n) {
    if (n < 2){
      return n
    }
    return fib(n - 1) + fib(n - 2)
}

// 使用记忆函数优化 fib 函数
fib = memoize(fib);

// 则下次我们调用 fib 函数时,当碰到重复计算的数就会直接从缓存中获取值,避免了重复计算。

这个 memoize 函数利用了JavaScript中对象字典的特性以及闭包的特性。存储在 cache 对象中的值可以在同一个函数中持久存在,可以随时被访问和更改。

记忆函数中缓存的有效期
可以添加一个缓存过期机制来设定有效时间,这样可以防止缓存无限量增长,或者处理那些可能会随时间而改变的数据。

具体的实现方式可能会有很多种,下面是一种简单的示例:

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

    return (...args) => {
        let key = JSON.stringify(args);

        if(key in cache && Date.now() - cache[key].time < ttl){
            return cache[key].value;
        } else {
            let value = func(...args);
            cache[key] = { value: value, time: Date.now() }; // 存储计算结果以及当前的时间戳
            return value;
        }
    };
}

在这个例子中,memoize 函数的第二个参数 ttl 代表缓存的有效时间(以毫秒为单位)。当我们从缓存中获取数据时,我们会检查数据的时间戳是否还在有效期内,如果是,我们就返回该值;否则,我们就重新计算结果,并存储新的值和当前的时间戳。

使用 LRU(Least Recently Used)算法来实现一个有容量限制的缓存,这样可以在缓存满了之后自动淘汰最久未使用的数据

// 创建一个新的LRU缓存实例
function LRUCache(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
}

// 获取键值对应的缓存值
LRUCache.prototype.get = function(key) {
    if(this.cache.has(key)) {
        // 移除并重新添加键值对,保持该键为最近使用
        let temp = this.cache.get(key);
        this.cache.delete(key);
        this.cache.set(key, temp);
        return temp;
    } else {
        // 如果键不存在,则返回-1
        return -1;
    }
};

// 添加/更新缓存
LRUCache.prototype.put = function(key, value) {
    if(this.cache.has(key)) {
        // 存在则先移除
        this.cache.delete(key);
    } else if(this.cache.size >= this.capacity) {
        // 缓存容量已满,移除最早加入的键值
        this.cache.delete(this.cache.keys().next().value);
    }
    this.cache.set(key, value);
};

LRUCache 实现了两个主要方法,get 和 put。get 方法用于获取存在的值,或当键不存在时返回 -1。如果获取到了值,就会移动当前的键值对到最近使用的位置。put 方法可以插入新的键值对,如果键已经存在,在添加新的键值对之前,要先删除老的键值对。如果缓存已满,就会删除最早(最少使用)的键值对。通过这种方式,缓存将始终维持在设置的容量以下。

LRU缓存是按照以下规则删除最早加入的键值对

LRU(Least Recently Used) 缓存的工作原理基于一个观察,即最近使用过的数据在未来很可能会再次被使用。因此,当空间满了,并且需要添加新的键值对时,应当去掉已有缓存中最久未被使用的数据。

更具体来说,每当在缓存中查询一个键值对时(无论是获取还是存储),都将其移至缓存队列的顶端。这样,最近被使用的键值对总是在队伍的顶端,而最久未被使用的键值对则总是在队伍的底端。

当添加新的键值对而缓存已满时,缓存将从底端删除最久未被使用的键值对,从而为新的键值对腾出空间。这就是LRU缓存的基本工作原理。

在JavaScript中,可以使用Map对象来实现这个功能,因为Map按照插入顺序来迭代元素 ---- 最新插入的元素在最后,最早插入的元素在最前。当删除并重新插入已有的键值对时,该键值对会自动被移到最后。这正是我们想要的行为:最近使用的数据始终在最后,最久未被使用的数据在最前。

因此,当LRU缓存需要删除最早的键值对以腾出空间时,只需要删除Map中的第一个元素即可。例如,this.cache.delete(this.cache.keys().next().value); 这行代码就能完成工作。

以上就是文章全部内容了,如果喜欢这篇文章的话,还希望三连支持一下,感谢!

标签:缓存,return,前端,cache,value,LRU,key,键值
From: https://blog.csdn.net/weixin_43891869/article/details/139402635

相关文章

  • Tiger Lowcode 低代码开发平台、Web前端设计器、LowcodeCore 快速构建API
    最近发现一款非常好用的低代码开发平台:Tiger低代码开发平台:http://www.tigerlowcode.com“TigerLowcode低代码平台”分为:“Web设计器”和“API设计器”两个部分。“Web设计器”是一个基于“CSS/Jquery/HTML”,用于实现“拖拉拽,所见即所得”的前端框架。“API设计器”是一个基于......
  • 【前端每日基础】day42——关于 Vuex 共有几个属性,哪里可以书写同步任务,哪里可以书写
    Vuex是Vue.js的一个状态管理模式,它集中式地存储和管理应用的所有组件的状态。Vuex提供了以下几个核心属性,每个属性在状态管理中有不同的用途:Vuex共有的几个属性:State:用于存储应用的状态。可以通过this.$store.state或在组件中通过mapState辅助函数访问。Gette......
  • web 前端技术的一些知识点分享~
    css的规则是由选择器和 组成的目录css的规则是由选择器和 组成的CSS(层叠样式表)的规则是由选择器和声明块组成的。选择器用于选定页面上的元素,这可以是一个元素标签(如 h1)、类(如 .classname)、ID(如 #idname)或是元素的状态(如 :hover)。选择器决定了哪些HTML元素将应......
  • Spring Boot入坑-6-缓存
    概述位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构,均可称之为缓存(Cache)典型的如CPU与内存之间L1、L2、L3缓存,能让CPU更有聪明、更高效的执行任务在软件项目中,相比于访问网络、磁盘、DB等介质或设备,内存具有更高的效率,所以很多的时候会利用内存作为......
  • 前端工程化工具系列(六)—— VS Code(v1.89.1):强大的代码编辑器
    VSCode(VisualStudioCode)是一款由微软开发的强大且轻量级的代码编辑器,支持多种编程语言,并提供了丰富的扩展插件生态系统。这里主要介绍如何使用配置ESLint、Stylelint等插件来提升开发效率。1自动格式化代码最终要达到的效果是:在对文件保存时自动格式化Vue、JS/TS......
  • 前端开发,块元素与行内元素
     块元素行内元素块元素会在页面中独占一行行内元素不会独占页面中的一行可以设置width/height属性设置width/height属性无效一般块级元素可以包含行内元素和其他块级元素一般行内元素包含行内元素,不包含块级元素 常见的块级元素div、form、h1~h6、hr、......
  • FastAdmin 后端控制器与前端页面传参
    1.菜单让链接带参 2.控制器传参数到前端JS$this->assignconfig('tab',$tab); 3.JS传参回后端index_url:'contract/contract/index/tab/'+Config.tab, ......
  • 前端开发标签1
    标签<html></html>标签,网页必需标签<head></head>标签,用于定义文档头部,文档的头部描述了文档各种属性和信息,包括文档的标题,在WEB中的未知以及和其他文档的关系,绝大多数文档头部包含的数据都不会真正座位内容显示给读者<title></title>标签,页面标题<meta>单标签,表示为编码格式......
  • nginx实现网页缓存防篡改
    简介使用网站防篡改对指定的敏感页面设置缓存,缓存后即使源站页面内容被恶意篡改,WAF也会向访问者返回预先缓存好的页面内容,确保用户看到正确的页面。启用 网页防篡改、敏感信息防泄露开关,才能使用该功能。填写精确的要防护的路径,可以防护该路径下的text、html和图片等内容......
  • redis自学(45)缓存同步
                             整个多级缓存的架构  ......