面试题答案
一键面试内存泄漏问题分析
- 循环引用:内部函数如果持有对外部函数作用域中对象的引用,而这些对象又持有对内部函数的引用,就可能形成循环引用。在某些旧版本浏览器(如IE)中,垃圾回收机制可能无法正确处理这种循环引用,导致相关对象无法被回收,从而造成内存泄漏。
- 不必要的引用保留:如果内部函数返回后,一直被外部代码持有引用,且内部函数又间接引用了外部函数作用域中的大量数据,即使这些数据在后续逻辑中不再需要,由于存在引用关系,垃圾回收器也不会回收这些数据,造成内存泄漏。
避免方法
- 解除循环引用:在适当的时机手动打破循环引用关系。例如,当不再需要某个对象时,将其引用设置为
null
。 - 减少不必要的引用:确保内部函数只引用必要的数据,避免过度引用外部函数作用域中的对象。同时,在内部函数不再使用时,及时释放对其的引用,以便垃圾回收器能够回收相关内存。
优化后代码示例
// 原始代码
function namespace() {
let largeData = { /* 大量数据 */ };
function innerFunction() {
// 使用 largeData
console.log(largeData);
}
return innerFunction;
}
let func = namespace();
// 优化后代码
function namespace() {
let largeData = { /* 大量数据 */ };
function innerFunction() {
let dataCopy = {...largeData }; // 只复制需要的数据
console.log(dataCopy);
largeData = null; // 及时释放对原始大数据对象的引用
}
return innerFunction;
}
let func = namespace();
在这个优化示例中,innerFunction
只复制了需要的数据,并且在使用完后将 largeData
设置为 null
,避免了不必要的引用,有助于垃圾回收器回收内存。