最简单的new Date()展示,也能做优化

问题诊断

首先,大家来看下这段代码

js 复制代码
function TimeDisplay() {
  const time = new Date().toLocaleTimeString();
  return <div>{time}</div>;
}

是不是看着很简单,很眼熟,很常见,但是这段代码每次渲染都会创建new Date()实例 ➔ 执行toLocaleTimeString() ➔ 触发垃圾回收,在高频更新场景下会产生不必要的性能损耗

优化方案

1. 静态时间展示(只需初始值)
js 复制代码
const [time] = useState(() => new Date().toLocaleTimeString()); // 初始化只执行一次
return <div>{time}</div>;
  • 优点:彻底避免重复实例化,且无副作用
  • 局限:时间不能自动更新
  • 适用场景:展示固定时间
2. useRef固定值
js 复制代码
const timeRef = useRef(new Date().toLocaleTimeString());
return <div>{timeRef.current}</div>;
  • 优点:避免重复实例化;内存占用稳定
  • 局限:时间永不更新
  • 适用场景:静态时间快照
3. useMemo空依赖缓存
js 复制代码
const time = useMemo(() => new Date().toLocaleTimeString(), []);
return <div>{time}</div>;
  • 优点:减少垃圾回收次数;代码简洁

  • 缺点:时间锁定初始值;滥用易导致隐蔽的 BUG

    这里解释一下所谓隐蔽的bug指的是什么

    useMemo是用来缓存结果,避免重复计算的,但是时间这个东西,我们在很多时候属于要么不更新,要么频繁更新,在这种情况下,如果组件频繁挂载或者卸载的话,旧的格式化器无法被GC回收,同时累积大量的缓存对象,会造成内存膨胀。

  • 适用场景:需要复杂计算的初始值缓存

4. useEffect基础动态更新
jsx 复制代码
const [time, setTime] = useState('');
useEffect(() => {
  const timer = setInterval(() => {
    setTime(new Date().toLocaleTimeString());
  }, 1000);
  return () => clearInterval(timer);
}, []);
  • 优点:实现动态更新时间;代码直观易理解
  • 缺点:多组件实例导致定时器泛滥;父组件渲染可能打断计时
  • 适用场景:独立组件的简单时钟
5. 单例模式 + 自定义 Hook
js 复制代码
// 单例服务
const timeService = {
  subscribers: new Set(),
  start() {
    setInterval(() => {
      const time = new Date().toLocaleTimeString();
      this.subscribers.forEach(cb => cb(time));
    }, 1000);
  }
};

// Hook封装
const useGlobalTime = () => {
  const [time, setTime] = useState('');
  useEffect(() => {
    timeService.subscribers.add(setTime);
    return () => timeService.subscribers.delete(setTime);
  }, []);
  return time;
};
  • 优点:全应用共享单一定时器;内存占用恒定 O(1)
  • 缺点:需要维护额外服务模块
  • 适用场景:企业级应用;多组件时间同步需求
6. Web Worker 后台计算
js 复制代码
// worker.js
self.onmessage = () => {
  setInterval(() => {
    self.postMessage(new Date().toLocaleTimeString());
  }, 1000);
};

// 组件
useEffect(() => {
  const worker = new Worker('worker.js');
  worker.onmessage = (e) => setTime(e.data);
  return () => worker.terminate();
}, []);
  • 优点:不阻塞主线程;适合复杂计算场景
  • 缺点:通信成本较高;增加构建复杂度
  • 适用场景:计算密集型任务(如实时图表渲染)
7. Intl.DateTimeFormat 高效格式化
js 复制代码
const formatter = useMemo(() => 
  new Intl.DateTimeFormat('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  }), []);

const [time, setTime] = useState('');
useEffect(() => {
  const timer = setInterval(() => {
    setTime(formatter.format(new Date()));
  }, 1000);
  return () => clearInterval(timer);
}, []);
  • 优点:性能比 toLocaleTimeString 快 3 倍;支持本地化配置
  • 缺点:需手动管理格式化实例
  • 适用场景:高频更新场景(如秒表);多语言/时区支持

项目中有很多很不起眼的代码,其实都可以进行优化,有的时候就是这些不起眼的小东西,累积起来会造成大麻烦,快去看看你的项目里有没有可以优化的时间吧,如果有更好的方法,欢迎评论区分享讨论

相关推荐
mCell8 小时前
GSAP ScrollTrigger 详解
前端·javascript·动效
gnip8 小时前
Node.js 子进程:child_process
前端·javascript
excel11 小时前
为什么在 Three.js 中平面能产生“起伏效果”?
前端
excel12 小时前
Node.js 断言与测试框架示例对比
前端
天蓝色的鱼鱼14 小时前
前端开发者的组件设计之痛:为什么我的组件总是难以维护?
前端·react.js
codingandsleeping14 小时前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
颜如玉14 小时前
HikariCP:Dead code elimination优化
后端·性能优化·源码
石金龙15 小时前
[译] Composition in CSS
前端·css
白水清风15 小时前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
Ticnix15 小时前
函数封装实现Echarts多表渲染/叠加渲染
前端·echarts