12、JavaScript常见的内存泄露问题 - JavaScript学习系列文章

多前端同学可能觉得这是浏览器或引擎该操心的事, 但理解内存管理能帮你写出更高效的代码, 还能避免各种内存泄漏的坑.

一、常见的内存泄露场景

  1. 意外的全局变量:
javascript 复制代码
function leaky() {`  leak = `'这是一个全局变量';  // 本意是 let leak = ...
`  `this.anotherLeak = '这也是全局的';  // 在非严格模式下,this 指向 window`}`
// 解决方法:使用严格模式 "use strict"
  1. 被遗忘的定时器和回调:
javascript 复制代码
// 定时器泄漏let someData = getHugeData();
setInterval(() => {`  `let node = document.getElementById('node');`  `if(node) {`    node.`innerHTML = JSON.stringify(someData);`  }``}, `1000);
// 即使移除 DOM 节点,定时器还在引用 someData 和 node
javascript 复制代码
// 事件监听泄漏function setup() {`  `let btn = document.getElementById('myButton');`  btn.`addEventListener('click', onClick);`}`
function onClick() {`  `console.log('clicked!');`}`
// 如果 btn 被移除但没解绑事件,相关内存无法释放
  1. 闭包的不当使用:
javascript 复制代码
function outer() {`  `let bigArray = new Array(1000000).fill('*');
`  `return function inner() {`    `console.log('inner');`    `// 即使不用 bigArray,它也会被保留,因为闭包保留了整个作用域链`  };``}`
let hold = outer();  // bigArray 无法被回收
  1. DOM引用未清理:
javascript 复制代码
let elements = {`  `button: document.getElementById('myButton'),`  `div: document.getElementById('myDiv')`};`
function removeDiv() {`  `document.body.removeChild(elements.div);`  `// 虽然从 DOM 移除了,但 elements.div 仍引用着这个节点`}`

二、内存优化技巧

  1. 合理使用变量作用域:
javascript 复制代码
// 不好的做法function process(data) {`  `let result = [];
`  `// 大数组处理...`  `for(let i = 0; i < data.length; i++) {`    result.`push(data[i] * 2);`  }`
`  `// 后续只使用 result 的前10项`  `return result.slice(0, 10);`  `// 但整个 result 数组会保留在内存中`}`
// 更好的做法function processBetter(data) {`  `let result = [];
`  `for(let i = 0; i < 10; i++) {  // 只处理需要的部分`    `if(i < data.length) {`      result.`push(data[i] * 2);`    }``  }`
`  `return result;  // 内存占用更小`}`
  1. 及时清理引用:
javascript 复制代码
// 定时器let timer = setInterval(() => {...}, 1000);// 不需要时clearInterval(timer);
// 事件监听function cleanUp() {`  btn.`removeEventListener('click', onClick);`}`
// WeakMap/WeakSet 允许对象被垃圾回收let weakMap = new WeakMap();let obj = {};`weakMap.`set(obj, 'some value');  // 如果 obj 被回收,weakMap 中的条目自动消失
  1. 分块处理大数据:
javascript 复制代码
// 处理大数组时不要一次性处理function processLargeArray(array, chunkSize, callback) {`  `let index = 0;
`  `function next() {`    `let chunk = array.slice(index, index + chunkSize);`    index += chunkSize;`
`    `if(chunk.length) {`      `callback(chunk, next);`    }``  }`
`  `next();`}`
// 使用processLargeArray(hugeArray, 1000, (chunk, next) => {`  `// 处理当前块`  `processChunk(chunk);
`  `// 使用 setTimeout 或 requestIdleCallback 给浏览器喘息机会`  `setTimeout(next, 0);`});`
  1. 使用对象池: 频繁创建销毁对象? 试试对象池:

    class ObjectPool { constructor(createFn) { this.createFn = createFn; this.pool = []; }
    get() { return this.pool.length ? this.pool.pop() : this.createFn(); }
    release(obj) { // 重置对象状态(如果需要) this.pool.push(obj); }}
    // 使用let particlePool = new ObjectPool(() => ({ x: 0, y: 0, vx: 0, vy: 0}));
    // 需要时let particle = particlePool.get();// 使用完后particlePool.release(particle);

相关推荐
辣知3 分钟前
辣知·化智56 良渚神权与夏朝颠覆
学习
Brilliantwxx25 分钟前
【STM32】 I2C_EEPROM_test 工程(实战篇)
开发语言·stm32·单片机·嵌入式硬件·ecmascript
dadaobusi25 分钟前
学习:三层交换机
学习
清水白石00830 分钟前
Python 异步编程深度解析:Cancellation 到底是异常还是控制信号?从 asyncio 取消机制到企业级事务设计最佳实践
开发语言·python
袋鼠云数栈UED团队32 分钟前
AI Coding 方法论分析:同一个需求 SpecKit 、 Superpowers、 MattpocockSkills 不同设计
前端·aigc·ai编程
kolyle37 分钟前
万级 QPS 下的 Token 分发系统架构:从 0 到 1 跑通 AI 时代的“水电煤“
开发语言·人工智能·系统架构·token·qps·极智词元·大模型私有化部署
掰头战士37 分钟前
Prompt Cache,如果agent全靠LLM方做隐式缓存实在不够用。
前端·llm·agent
caoerzhong1 小时前
JeeWMS 开源仓库管理系统 GPL-3.0 合规指南:Java WMS 二次开发前必须弄清的授权边界
java·开发语言·开源·vue
Patrick在香港1 小时前
Python 审计香港开放数据目录:两个端点差 10 倍,只有 9.3% 的资源标了「最后修改时间」
开发语言·数据库·python·数据分析·api·数据治理·开放数据
笨鸟先飞的橘猫1 小时前
树结构在游戏行业中的应用
学习·游戏