JavaScript 内存优化 GC 回收 与 var let 和 const 1/2

2026年元旦以来,中股市场继续牛市上涨。我们观测的 UfqiFina 有福金融 里的基金也出现了大量呈现买入信号可选标的,随之而来的是计算量也逐渐增大。

由于在设计上,UfqiFina 的一些计算需要放到前端浏览器内进行,随着计算量的增大,依赖 JavaScript 的程序在运行中逐渐曝露出运行时间长,内存消耗逐步增加的问题。这对计算资源的需求宛如过去一年中国证券市场一样,逐步上扬。迫不得已,我们借助 AI助手 抖音豆包 ,有针对性地对 UfqiFina 金融涉及到的 Hanjst 进行性能及内存方面的优化和提升。

大致结论,通过下面这些改进,UfqiFina 实现对一组候选基金进行扫描时,所占用的内存由修改前的:
峰值 3000MB~5000MB ,降低为 500MB~1500MB 。大约 2 倍 至 10 倍 的优化提升。
Hanjst 此番的修改主要是在变量声明和使用中 使用 let / const 替换 var ,并增加相应大数据对象的显式销毁声明。

A1. JavaScript 的内存管理 GC 回收

JavaScript 是自动垃圾回收的语言,不需要手动分配 / 释放内存,GC 的核心目标是回收 “不再被使用” 的内存空间。GC 自动执行,但如果代码写得不当,会导致 “内存泄漏”(本该回收的内存无法被回收),最终引发页面卡顿、崩溃。以下是最实用的优化手段:

1. 避免意外的全局变量

全局变量挂载在 window 上,生命周期和页面一致,不会被 GC 回收,是最常见的内存泄漏原因。

// 错误示例:未声明的变量隐式成为全局变量
function test() {
  // 未用 let/const/var 声明,会挂到 window 上
  unGlobalVar = { data: new Array(1000000) }; 
}
test(); // 这个大数组永远不会被回收

// 正确做法:
// 1. 使用 let/const 限制作用域
function test() {
  const localVar = { data: new Array(1000000) };
  // 用完后手动置 null(非必需,但大对象建议)
  localVar = null; 
}

2. 及时清理 DOM 引用

如果变量保存了 DOM 元素的引用,即使 DOM 被从页面移除,该引用仍会阻止 GC 回收,导致内存泄漏。javascript运行

// 错误示例:DOM 被删除但引用还在
const btn = document.getElementById('btn');
document.body.removeChild(btn); 
// btn 变量仍引用该 DOM,内存无法回收

// 正确做法:删除 DOM 后清空引用
const btn = document.getElementById('btn');
document.body.removeChild(btn);
btn = null; // 解除引用,GC 可回收

3. 清除定时器 / 事件监听器

定时器(setInterval/setTimeout)和事件监听器如果不手动清除,其回调函数及内部引用的对象永远不会被回收。javascript运行

// 错误示例:定时器未清除
setInterval(() => {
  console.log('未清除的定时器');
  // 内部引用的大对象永远无法回收
}, 1000); 

// 正确做法:保存定时器ID,不用时清除
const timerId = setInterval(() => {
  console.log('可回收的定时器');
}, 1000);
// 页面卸载/不需要时清除
clearInterval(timerId);

4. 使用弱引用(WeakMap/WeakSet)

Map/Set 的键是强引用,会阻止 GC 回收;而 WeakMap/WeakSet 的键是弱引用,不会阻止 GC 回收,适合存储临时关联数据。javascript运行

// Map(强引用):即使 dom 被删除,Map 仍引用它,无法回收
const map = new Map();
const dom = document.getElementById('dom');
map.set(dom, '附加数据');
document.body.removeChild(dom); 
// dom 仍被 Map 引用,内存泄漏

// WeakMap(弱引用):dom 被删除后,GC 自动回收对应的键值对
const weakMap = new WeakMap();
const dom = document.getElementById('dom');
weakMap.set(dom, '附加数据');
document.body.removeChild(dom); 
// dom 无其他引用,GC 会回收 dom 及 weakMap 中的对应条目

以上4个方面对改善 JavaScript 运行时的内存占用分析,都有一定的道理。在 UfqiFina 的实践中,主要进行了前 3 项的改进,替换变量的声明关键词,及时清理 DOM 引用 和 清除 定时器,

先说清除 JavaScript 中的定时器,JavaScript 本身没有内置 API 直接获取所有已创建的定时器 ID,因为浏览器会自动分配递增的数字 ID,但不会暴露所有 ID 的列表。因此核心思路是:

  1. 拦截并重写原生定时器方法,记录所有创建的定时器 ID;
  2. 遍历记录的 ID 统一清除,同时利用浏览器的兼容特性(clearTimeoutclearInterval 可以互相替代,清除对方类型的定时器)简化逻辑。
// 1. 保存原生的 setTimeout/setInterval 方法,避免覆盖后无法恢复
const nativeSetTimeout = window.setTimeout;
const nativeSetInterval = window.setInterval;

// 2. 定义数组存储所有定时器 ID
const timerIds = new Set(); // 使用 Set 避免重复 ID(虽然理论上 ID 不会重复,但增加容错)

// 3. 重写 setTimeout,记录所有创建的 timer ID
window.setTimeout = function (callback, delay, ...args) {
  const timerId = nativeSetTimeout(callback, delay, ...args);
  timerIds.add(timerId); // 记录 ID
  return timerId; // 保留原生返回值,不影响原有逻辑
};

// 4. 重写 setInterval,记录所有创建的 interval ID
window.setInterval = function (callback, delay, ...args) {
  const intervalId = nativeSetInterval(callback, delay, ...args);
  timerIds.add(intervalId); // 记录 ID
  return intervalId; // 保留原生返回值
};

// 5. 核心函数:一次性清除所有定时器(timer + interval)
function clearAllTimers() {
  // 遍历所有记录的 ID 并清除
  for (const id of timerIds) {
    try {
      // 兼容处理:clearTimeout 可清除 interval,clearInterval 也可清除 timeout
      clearTimeout(id); 
      clearInterval(id);
    } catch (e) {
      // 忽略无效 ID 的报错(比如已被手动清除的 ID)
      console.debug('清除定时器 ID 失败:', id, e);
    }
  }
  // 清空记录的 ID 列表,避免重复清除
  timerIds.clear();
}

// 6. 可选:恢复原生定时器方法(如果需要)
function restoreNativeTimers() {
  window.setTimeout = nativeSetTimeout;
  window.setInterval = nativeSetInterval;
  timerIds.clear();
}

下一篇继续写 使用 let / const 替换 var .

此条目发表在-GTAjax, -Hanjst/-汉吉斯特, 计算机技术分类目录,贴了, , , 标签。将固定链接加入收藏夹。

JavaScript 内存优化 GC 回收 与 var let 和 const 1/2》有2条回应

  1. Wadelau说:

    下一篇:
    https://ufqi.com/go/?mod=blog&id=3732&tit=JavaScript 内存优化 GC 回收 与 var let 和 const 2/2

  2. Pingback引用通告: JavaScript 内存优化 GC 回收 与 var let 和 const 2/2 | -UFQI-Blog

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code