Jackson Sophat

Lazy 函数

定义

惰性函数(Lazy Function)也可以叫做惰性求值(Lazy Evaluation)

在编程语言理论中,惰性求值(英语:Lazy Evaluation),又译为惰性计算、懒惰求值,也称为传需求调用(call-by-need),是计算机编程中的一个概念,目的是要最小化计算机要做的工作。惰性计算的最重要的好处是它可以在空间复杂度上得到极大的优化,从而可以轻易构造一个无限大的数据类型。

例子

copyToClipboard函数 lazy 化以后,if (navigator.clipboard)条件在一个运行时中只需运行一次。

before
1
2
3
4
5
6
7
function copyToClipboard(text) {
if (navigator.clipboard) {
// ...
} else {
// ...
}
}
after
1
2
3
4
5
6
7
8
9
10
11
12
function copyToClipboard(text) {
if (navigator.clipboard) {
copyToClipboard = function () {
// ...
};
} else {
copyToClipboard = function () {
// ...
};
}
copyToClipboard(text);
}
copyToClipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function copyToClipboard(text) {
if (navigator.clipboard) {
copyToClipboard = function () {
navigator.clipboard.writeText(text);
};
} else {
copyToClipboard = function () {
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand("copy");
} catch (err) {}
document.body.removeChild(textArea);
};
}
copyToClipboard(text);
}

在 Vue/React 中?

在 Vue 和 React 中,也有一些内建特性或 API 使用了 惰性求值,主要用于性能优化,避免不必要的计算。

React

特性 / API是否惰性说明
useMemo(fn, deps)✅ 是只有依赖变化时才会调用 fn,否则返回上一次缓存的值。
useCallback(fn, deps)✅ 是类似 useMemo,用于缓存函数引用,避免子组件重新渲染。
React.lazy(() => import())✅ 是动态导入组件,直到需要渲染才加载对应模块。
Suspense + lazy✅ 是React.lazy 配套使用,延迟加载资源直到用到。
useDeferredValue⚠️ 部分惰性它是“延迟更新”而不是惰性求值,用于低优先级渲染。
useTransition⚠️ 延迟渲染用于延迟某些更新,是“延迟调度”而非真正惰性计算。

Vue

特性 / API是否惰性说明
computed✅ 是只有依赖发生变化时才会重新计算,否则返回缓存值。
watchEffect✅ 是虽然自动收集依赖,但执行体在依赖首次建立后才运行。
defineAsyncComponent✅ 是类似 React.lazy,组件只在真正用到时才会被加载。
v-once✅ 是渲染一次后就不会再参与更新了,类似静态缓存。
suspense✅ 是用于处理异步组件加载,与 async component 配合使用。

小结

惰性求值通常出现在以下场景:

  • 性能优化:避免重复执行昂贵计算(如 computed, useMemo)。
  • 懒加载:减少首屏体积(如 React.lazy, defineAsyncComponent)。
  • 副作用控制:只有依赖变化才触发副作用(如 watch, useEffect)。