第 10 卷
- 开启`strict`模式(`'use strict'`),未声明的变量会直接报错,从根源避免意外全局变量;
- 变量声明必用`let/const`,避免使用`var`(`var`存在变量提升和全局污染风险);
• 不再使用的全局变量,手动置空释放:`window.data = null`(浏览器)、`delete global.data`
(Node.js)。
- 合理管理闭包,及时释放引用
• 避免闭包长期引用大对象,若必须引用,业务结束后手动清空闭包引用:`persistentClosure =
null`;
- 闭包内仅保留必要的引用,避免引用整个外部函数作用域;
- 组件销毁/页面卸载时,清空所有与闭包相关的引用变量。
- 及时移除事件监听
• DOM元素移除前,通过`removeEventListener`移除对应的事件监听(注意:监听函数必须与绑
定的是同一个引用);
• 组件生命周期销毁时(如React的`componentWillUnmount`、Vue的`beforeUnmount`),批
量清理所有事件监听;
- 优先使用事件委托(如委托到`document`),减少事件监听数量,避免重复绑定。
- 严格清理定时器/计时器
• 定时器/计时器使用后,务必通过`clearTimeout`/`clearInterval`清理,尤其是在组件销毁、页
面卸载时;
• 将定时器ID存储在实例属性中,便于后续清理:`this.timer = setTimeout(...)`,销毁时执行
`clearTimeout(this.timer)`;
- 避免使用无期限的`setInterval`,优先使用`setTimeout`递归(可灵活控制终止时机)。
- 避免僵尸DOM,及时清空DOM引用
- DOM元素移除后,立即将对应的JS引用变量置空:`container = null`;
• 避免在JS中长期缓存DOM元素,优先通过`document.querySelector`动态获取,减少不必要的
DOM引用;
- 组件销毁时,清空所有DOM相关的引用属性(如`this.$refs`)。
- 合理管理异步任务和缓存
• 异步任务(Promise/AJAX)确保完成:无论成功/失败,都调用`resolve/reject`;使用
`AbortController`取消未完成的请求;
• 内存缓存设置上限和过期机制:使用`lru-cache`等成熟缓存库(自动淘汰最近最少使用的缓
• 优先使用`WeakMap/WeakSet`作为缓存:它们的键是弱引用,当键对应的对象无其他引用时,会
- 借助工具检测,提前排查泄漏
• 浏览器端:使用Chrome开发者工具(Memory面板),通过HeapSnapshot(堆快照)对比内存
占用,查找未回收的对象;使用Performance面板录制运行过程,观察内存变化趋势;
• Node.js端:使用`--inspect`参数启动服务,通过Chrome开发者工具调试;使用`clinic.js`、
`memwatch-next`等工具监控内存占用,定位泄漏点;
• 代码规范:定期进行代码评审,重点检查闭包、事件监听、定时器、缓存等易泄漏场景;上线前进
行压力测试,验证内存稳定性。
四、核心总结
JavaScript内存泄漏的本质是“无用对象被意外保留引用”,避免泄漏的核心原则是:明确对象的生命周期,在不使用时主动释放引用。开发中需重点关注闭包、事件监听、定时器、DOM引用四大场
景,结合工具检测,提前排查潜在泄漏风险,确保程序长期稳定运行。
(注:文档部分内容可能由 AI 生成)
全站分卷索引 · 10 卷
- 1第 1 卷
- 2第 2 卷
- ◦ 处理样式优先级(!important > 行内样式 > ID选择器 > 类/伪类/属性选择器 > 标签/伪元素选择
- 关键特性
- 6. 详述浏览器加载和执行JavaScript文件的机制
- JS加载执行核心机制(单线程+阻塞特性)
- • 浏览器解析HTML时,遇到 <script> 标签,立即暂停后续HTML解析,发起HTTP请求加载JS文
- • 可通过属性优化加载:
- ◦ async:异步加载,加载完成后立即执行(执行顺序不确定,不阻塞HTML解析,阻塞渲
- ◦ defer:异步加载,HTML解析完成后、DOMContentLoaded事件前执行(执行顺序与标签
- ◦ type="module":ES6模块加载,默认异步,遵循 defer 规则,支持按需加载、作用域隔
- • V8引擎采用即时编译(JIT):将AST转换为字节码,再将热点代码(频繁执行)编译为机器码,
- 关键特性
- • 异步JS(async/defer/module)仅解除对HTML解析的阻塞,仍会阻塞 DOMContentLoaded 事
- 3第 3 卷
- 4第 4 卷
- 5第 5 卷
- 6第 6 卷
- ✅ 2. 微任务的优先级和执行时机不同
- ✅ 3. 宏任务的类型和优先级不同
- ✅ 4. 页面渲染的差异
- • Node.js事件循环:无页面渲染环节,Node.js是服务端运行环境,无需渲染页面,专注于I/O处
- ✅ 5. 异步API的支持差异
- • 浏览器:支持DOM事件、AJAX、requestAnimationFrame、MutationObserver等前端专属异步
- • Node.js:支持文件I/O、网络I/O、child_process、setImmediate、process.nextTick等服务端专
- ✅ 6. 任务队列的数量差异
- ✅ 核心差异总结表
- 17. 描述process.nextTick在Nodejs事件循环中的执行顺序及其与微任务
- 的关系
- process.nextTick的定义
- 7第 7 卷
- 8第 8 卷
- 9第 9 卷
- 10第 10 卷
- • 不再使用的全局变量,手动置空释放:`window.data = null`(浏览器)、`delete global.data`
- • 避免闭包长期引用大对象,若必须引用,业务结束后手动清空闭包引用:`persistentClosure =
- • DOM元素移除前,通过`removeEventListener`移除对应的事件监听(注意:监听函数必须与绑
- • 组件生命周期销毁时(如React的`componentWillUnmount`、Vue的`beforeUnmount`),批
- • 定时器/计时器使用后,务必通过`clearTimeout`/`clearInterval`清理,尤其是在组件销毁、页
- • 将定时器ID存储在实例属性中,便于后续清理:`this.timer = setTimeout(...)`,销毁时执行
- • 避免在JS中长期缓存DOM元素,优先通过`document.querySelector`动态获取,减少不必要的
- • 异步任务(Promise/AJAX)确保完成:无论成功/失败,都调用`resolve/reject`;使用
- • 内存缓存设置上限和过期机制:使用`lru-cache`等成熟缓存库(自动淘汰最近最少使用的缓
- • 优先使用`WeakMap/WeakSet`作为缓存:它们的键是弱引用,当键对应的对象无其他引用时,会
- • 浏览器端:使用Chrome开发者工具(Memory面板),通过HeapSnapshot(堆快照)对比内存
- • Node.js端:使用`--inspect`参数启动服务,通过Chrome开发者工具调试;使用`clinic.js`、