大对象频繁创建导致内存飙升怎么办?
我在做一个数据可视化项目,每次切换时间范围都会生成一个包含上万条数据的大对象,页面内存占用很快就飙到1G以上,浏览器都卡死了。
试过用 delete 删除旧数据,也手动把变量设为 null,但内存还是不释放。Chrome DevTools 里看 heap snapshot,这些大对象一直挂着,是不是我清理的方式不对?
function loadData(range) {
const oldData = this.currentData;
this.currentData = null; // 尝试清空
if (oldData) delete oldData;
// 模拟加载大量数据
this.currentData = Array.from({ length: 20000 }, (_, i) => ({
id: i,
value: Math.random() * 100,
timestamp: Date.now() - i * 60000
}));
}
delete用来删对象属性还行,但对局部变量使用基本等于没用。而且设置为 null 不代表马上释放,V8 的 GC 有自己的回收机制。核心问题是:你以为清掉了,但实际上还有引用挂着你没发现。
检查这几个地方:
第一,闭包泄漏。如果你的
loadData函数里定义了回调函数或者返回了函数,这些函数可能捕获了this.currentData的引用。检查一下有没有这样的代码:第二,事件监听器没解绑。每次加载数据时如果绑了事件监听器,旧数据可能还被监听器持有着。
第三,试试强制触发 GC。在 Chrome DevTools 里按 Shift+Esc 打开任务管理器,右键勾选"JavaScript 使用的内存",然后手动点击垃圾回收按钮看看能不能降下来。如果能降,说明是正常回收延迟;如果降不了,那就是有引用没断掉。
最直接的修复方式是这样的:
不过说真的,上万条数据每次全量加载本身就是问题。浏览器处理两万个对象本身就吃力,你得考虑:
分页加载或者虚拟列表,只渲染可视区域的数据
用 ArrayBuffer 或者 TypedArray 存数值型数据,减少对象数量
时间范围太大的时候做数据采样,别真拉两万条
内存问题十有八九是引用链没断干净,用 DevTools 的 Memory 面板做一次 Retaining Path 分析,看看哪个路径一直拽着你的数据不放。