Skip to content

Commit 677bb6a

Browse files
committed
chore(ci): blog sync
1 parent 4b9f51b commit 677bb6a

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: Vue源码——工具函数cached
3+
date: 2023-12-23T12:24:22Z
4+
summary:
5+
tags: []
6+
---
7+
8+
## 前言
9+
在 Vue 的源码中使用了很多自己封装的通用工具函数,
10+
11+
12+
13+
## cached 的缓存原理
14+
在阅读 Vue 源码过程中我发现它封装了一个有意思的函数,它可以将一个函数的返回值进行缓存,在 Vue 中使用频次也比较高的,有十九次!<u>ps.为了方便阅读,这里 flow 的类型我删掉了</u>
15+
![](http://cdn.liuji.site/illustration/1070/2022-11-10_22-42-56.jpg)
16+
我们来研究研究这个函数怎么做到缓存的:
17+
```
18+
export function cached(fn) {
19+
const cache = Object.create(null)
20+
return (function cachedFn (str) {
21+
const hit = cache[str]
22+
return hit || (cache[str] = fn(str))
23+
})
24+
}
25+
```
26+
这是一个高阶函数,传入一个函数,返回的也是一个函数,使用了闭包的原理,维持了 cache 对象不被销毁。
27+
首先呢,它声明了一个空的对象,通过传入的参数 str 去访问对象中的 str 属性,将该值赋值给 hit,这个 hit 命名也十分的形象,意为:击、打
28+
- 若未击中,也就是 hit 为 undfined,则将传入的函数返回值存入 cache[str]
29+
- 若击中,也就是已经存入了值,则直接返回这个值
30+
光说可能是比较抽象,我们上demo:
31+
32+
```
33+
var capitalize = cached(function (str) {
34+
return str.charAt(0).toUpperCase() + str.slice(1);
35+
});
36+
console.log(capitalize("abc"), "第一次访问");
37+
console.log(capitalize("abc"), "第二次访问");
38+
```
39+
在首次调用时,函数 cached 内部创建一个空的对象 cache,返回一个函数,这个函数里将 cache[str] 赋值给 hit,然后进行返回,此时我们是未击中的。因为闭包的缘故,这个函数被缓存到 cache对象里,不会被销毁,在我们第二次执行时不用再创建一个新的函数,而是直接调用缓存的函数。
40+
![](http://cdn.liuji.site/illustration/1070/2022-11-10_23-36-05.jpg)
41+
总的来说,这个函数可以将传入函数的参数作为 key,返回值作为 value,存储到闭包对象里。
42+
43+
## makeMap
44+
同样是利用闭包的原理,此函数接收一个字符串 str 和一个布尔值 expectsLowerCase,返回一个函数,返回的函数通过参数从 map 中取出 value,如果 expectsLowerCase 为true,取值函数参数字符串无论大小写,都会取出小写 key 的 value。
45+
```
46+
export function makeMap (
47+
str: string,
48+
expectsLowerCase?: boolean
49+
): (key: string) => true | void {
50+
// 创建一个干净的map
51+
const map = Object.create(null)
52+
// 将参数切成数组
53+
const list: Array<string> = str.split(',')
54+
// 遍历循环在 map 中增加 key,value 为 true
55+
for (let i = 0; i < list.length; i++) {
56+
map[list[i]] = true
57+
}
58+
59+
return expectsLowerCase
60+
? val => map[val.toLowerCase()]
61+
: val => map[val]
62+
}
63+
```
64+
65+
66+

0 commit comments

Comments
 (0)