对vue源码之缓存的研究--------------引用
探索vue源码之缓存篇
一、从链表说起
首先我们来看一下链表的定义:
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)
其中的双向链表是我们今天的主角:
双向链表也叫双链表。双向链表中不仅有指向后一个节点的指针,还有指向前一个节点的指针。这样可以从任何一个节点访问前一个节点,当然也可以访问后一个节点,以至整个链表。一般是在需要大批量的另外储存数据在链表中的位置的时候用。
图示如下

想象一群人手拉手站成一排,除了队头跟队尾,可以根据每个人的左手以及右手找到排在其左边或者右边的人,这也可以看成一种双向链表
而在vue.js中,作者正是利用类似双向链表的方式实现缓存的利用
二、LRU算法
在缓存中,利用类似双向链表来管理缓存并不难的。难的是如何更加高效的管理缓存,如何在缓存达到其最大内存空间,删除程序中最不常用的变量,而不是随机删除,造成最常用的变量被误删的情况。
vue.js中采用LRU算法来实现缓存的高效管理。
LRU是Least Recently Used的简称,具体内容可以查看GitHub,其有以下优点:
基于双向链表改变缓存对象中entry的排序,复杂度低
缓存对象有一个head(最近最少使用的项)和一个tail(最近最多使用的项)
head和tail都是entry,一个entry可能会有一个newer entry以及一个older entry(双向链接,older entry更接近head,newer entry更接近tail)
使用一个key就可以遍历这个缓存对象,也就意味着只有o(1)的复杂度,内存消耗非常小
可以通过下面的图来更好的理解LRU算法:

如果缓存达到最大,那么每次只需要将head删除就行了,保证了删除的项是最不常用的项
还是拿站成一排的人来举例。
有两个指示牌,上面分别写着tail以及head。head指向队伍的第一个人,tail指向队伍的最后一个人。
假设队伍有10个人,按照队伍的排列从队首到队尾依次编号a b c d ··· j,head指向a,tail指向j。
下面分成五种情况来说明队伍的变化:
如果叫到a(使用了数组里面第一个变量),就将a放到队尾,再手拉手重新组成一个新的队伍。并将原来指向j的tail现在指向a。再让原来指向a的head指向现在队伍的第一个人b
如果叫到b c d ··· i之间任何一个人,则将其从队伍中抽出,放到队尾,重新排队,再改变tail的指向为这个人
如果叫到j,则保持队伍不变
队伍达到最大人数,则去掉head指向的编号a,并改变head指向编号b,再在队尾增加一个人,假定编号为k,最后则将tail指向编号k
队伍没有达到最大人数,需要增加队伍人数。只需要在队尾增加编号为k的人。再将tail指向编号k
三、源码分析
我们可以通过一张图来先简单理解作者的数据结构:

作者在caches对象的_keymap里面保存所需要缓存的变量,通过older以及newer这两个属性来实现双向链表。older指向其前一个对象,newer指向其后一个对象。通过这两个属性,将缓存中的变量连接起来。
以上图举例:
缓存caches这个对象中保存了三个变量:key1、key2、key3。
header指向key1
tail指向key2
指向如下:

下面我们来看作者对这些数据的处理所使用的方法
文件位置:src/cache.js
首先export构造函数Cache

接下来作者在Cache的原型链上面分别定义了:
put:在缓存中加入一个key-value对象,如果缓存数组已经达到最大值,则返回被删除的entry,即head,否则返回undefined
shift:在缓存数组中移除最少使用的entry,即head,返回被删除的entry。如果缓存数组为空,则返回undefined
get:将key为传入参数的缓存对象标识为最常使用的entry,即tail,并调整双向链表,返回改变后的tail。如果不存在key为传入参数的缓存对象,则返回undefined
a) get:

b) put:

c) shift:

四、后记
从整个的代码来看,需要学习的不仅仅是LRU算法,作者的对于Object的处理方式也值的我们评味一番。
没有选择去遍历entry,选择通过在Cache内增加一个_keymap属性,通过这个属性来管理entry,实现key与newer、older状态的分离,减少代码的复杂度
对vue源码之缓存的研究--------------引用的更多相关文章
- 入口文件开始,分析Vue源码实现
Why? 网上现有的Vue源码解析文章一搜一大批,但是为什么我还要去做这样的事情呢?因为觉得纸上得来终觉浅,绝知此事要躬行. 然后平时的项目也主要是Vue,在使用Vue的过程中,也对其一些约定产生了一 ...
- 入口开始,解读Vue源码(一)-- 造物创世
Why? 网上现有的Vue源码解析文章一搜一大批,但是为什么我还要去做这样的事情呢?因为觉得纸上得来终觉浅,绝知此事要躬行. 然后平时的项目也主要是Vue,在使用Vue的过程中,也对其一些约定产生了一 ...
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- Vue源码探究-状态初始化
Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...
- vue源码之响应式数据
分析vue是如何实现数据响应的. 前记 现在回顾一下看数据响应的原因. 之前看了vuex和vue-i18n的源码, 他们都有自己内部的vm, 也就是vue实例. 使用的都是vue的响应式数据特性及$w ...
- Vue 源码解读(8)—— 编译器 之 解析(上)
特殊说明 由于文章篇幅限制,所以将 Vue 源码解读(8)-- 编译器 之 解析 拆成了上下两篇,所以在阅读本篇文章时请同时打开 Vue 源码解读(8)-- 编译器 之 解析(下)一起阅读. 前言 V ...
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- Vue源码后记-其余内置指令(3)
其实吧,写这些后记我才真正了解到vue源码的精髓,之前的跑源码跟闹着玩一样. go! 之前将AST转换成了render函数,跳出来后,由于仍是字符串,所以调用了makeFunction将其转换成了真正 ...
- 大白话Vue源码系列(01):万事开头难
阅读目录 Vue 的源码目录结构 预备知识 先捡软的捏 Angular 是 Google 亲儿子,React 是 Facebook 小正太,那咱为啥偏偏选择了 Vue 下手,一句话,Vue 是咱见过的 ...
随机推荐
- FileSystemWatcher监听文件事件
现有一个需求如下:监控某个目录中的文件修改,创建,删除等信息,并记录下来. 这里用到FileSystemWatcher类.由于考虑到文件的写入量会很频率,所以考虑先将监听到的消息记录到内存中. 监听部 ...
- bi的tableau
参考: 官网: https://help.tableau.com/current/server-linux/zh-cn/get_started_server.htm 可视化分析最佳做法: 实用指南 h ...
- Linux 下面根据端口号 查询 可执行程序的路劲的方法
1. 安装上lsof 的包 2. 使用 lsof 命令查看相关进程 lsof -i: 效果为: 3. 根据/proc 的目录查看可执行目录的文件位置 ll /proc/procid # procid ...
- [转帖]软件的变革与 AOT
软件的变革与 AOT https://www.colabug.com/851475.html 文章写的很牛B .. 前言 AOT 即 Ahead of Time Compilation,即运行前编,与 ...
- JavaScript学习总结(一)——闭包、对象、函数
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- MFC,QT与WinForm,WPF简介
编程语言的组成编程语言做为一种语言自然和英语这些自然语言有类似的地方.学英语时我们知道要先记26个字母,然后单词及其发音,接下来就是词组,句子.反正简单的说就是记单词,熟悉词法,句法.接下来就是应用了 ...
- 使用Tomcat、JNDI与ActiveMQ实现JMS消息通信服务
前言 之所以使用JNDI 是出于通用性考虑,该例子使用JMS规范提供的通用接口,没有使用具体JMS提供者的接口,这样可以保证我们编写的程序适用于任何一种JMS实现(ActiveMQ.HornetQ等) ...
- vue单页(spa)前端git工程拆分实践
背景 随着项目的成长,单页spa逐渐包含了许多业务线 商城系统 售后系统 会员系统 ... 当项目页面超过一定数量(150+)之后,会产生一系列的问题 可扩展性 项目编译的时间(启动server,修改 ...
- WebSocket的使用(基于VUE与SpringBoot)
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 We ...
- 使用 dataset 管理数据(官网)
ECharts 4 开始支持了 dataset 组件用于单独的数据集声明,从而数据可以单独管理,被多个组件复用,并且可以基于数据指定数据到视觉的映射.这在不少场景下能带来使用上的方便. ECharts ...