js
export const emptyObject = {}
export const emptyArray = []
export const noop = () => {}
在前端开发(尤其是 React、Vue 等现代框架)中非常常见,它们的作用是提升性能和避免不必要的渲染。下面我们来详细解释这三行代码的原理、用途以及可能的扩展用法。
✅ 一、emptyObject = {}
原理:
- 创建一个空对象字面量
{}
。 - 因为它是
const
定义的常量,在整个应用生命周期中地址不会变(即引用不变)。
用途:
- 防止组件因 props 引用变化而重新渲染。
- 在 React 或 Vue 中,如果父组件传给子组件的对象每次都是新的
{}
,即使内容一样,也会触发不必要的 diff 和 render。
示例场景(React):
jsx
function MyComponent({ config = {} }) { ... }
上面写法每次调用组件时都会创建一个新的 {}
,导致 config
的引用变化,从而引起不必要的更新。
改为:
jsx
import { emptyObject } from './utils'
function MyComponent({ config = emptyObject }) { ... }
这样无论多少次调用,只要没有传入 config
,默认值始终指向同一个内存地址,不会触发更新。
✅ 二、emptyArray = []
原理:
- 同上,创建一个空数组字面量
[]
,且引用固定不变。
用途:
- 防止因数组引用变化引起的不必要更新或副作用执行。
- 常用于
useEffect
、useMemo
、useCallback
的依赖项数组中,或者作为默认值传递给子组件。
示例场景(React):
js
useEffect(() => {
// do something
}, [list]) // 如果 list 是 [] 每次都新生成,会不断触发 effect
优化方式:
js
import { emptyArray } from './utils'
const list = data || emptyArray
✅ 三、noop = () => {}
原理:
noop
是 "no operation" 的缩写,表示一个空函数。- 这个函数不做任何事情,返回
undefined
。
用途:
- 当某些 API 要求必须传一个回调函数但你不希望它做任何事时使用。
- 防止因为传入
undefined
导致运行时报错。 - 提高性能:避免临时定义匿名函数造成额外开销(如在循环中)。
示例场景(React):
jsx
<MyButton onClick={onSubmit || () => {}} />
优化为:
jsx
import { noop } from './utils'
<MyButton onClick={onSubmit || noop} />
其他常见用途:
- 占位函数(防止 undefined)
- 默认事件处理器
- 单元测试中 mock 函数
🧠 总结对比表:
名称 | 类型 | 是否可变 | 主要作用 | 使用场景示例 |
---|---|---|---|---|
emptyObject |
Object | ❌ 不可变 | 避免对象引用变化造成的重渲染 | 默认 props |
emptyArray |
Array | ❌ 不可变 | 防止数组引用变化导致 useEffect 执行 | 默认列表数据 |
noop |
Function | ❌ 不可变 | 占位函数,防止 undefined 错误 | 空回调函数 |
🔍 扩展建议
1. 抽象成工具库(utils.js)
你可以统一导出这些"不可变默认值"供项目全局使用:
js
// utils.js
export const emptyObject = {}
export const emptyArray = []
export const noop = () => {}
export const identity = x => x
export const alwaysTrue = () => true
export const alwaysFalse = () => false
2. 在 TypeScript 中增强类型
为了更好的类型安全,可以加上类型注解:
ts
export const emptyObject: Record<string, never> = {}
export const emptyArray: readonly never[] = []
export const noop: () => void = () => {}
3. 在 React hooks 中使用
tsx
import { useMemo, useCallback } from 'react'
import { emptyObject, emptyArray, noop } from './utils'
function useCustomHook(data = emptyArray) {
const processedData = useMemo(() => process(data), [data])
const handleClick = useCallback(noop, [])
}
📌 小贴士
- 这些技巧属于微优化,在大型项目或高频更新组件中特别有效。
- 不推荐过度使用,比如对简单组件没必要刻意替换
{}
。 - 在 Redux selector、React Query、SWR 等状态管理中也广泛使用类似模式。
如果你正在开发一个大型 React/Vue 应用,合理使用 emptyObject
、emptyArray
、noop
可以显著减少不必要的 re-render 和副作用执行,提高整体性能与稳定性。