挑战更文更新面试题系列,趁着更文活动把一些常见的面试题进行一下整理,本次文章更新的是对内存泄露的一些针对的问题,上一篇讲了几个比较理论性的内存泄露的问题,这一篇做一个小的补充,补充一下
全局变量
全局变量是每次在面试的时候对于内存泄露一个比较基本的回答,因为这个是在日常开发中最容易犯的一个错误,对于全局变量联想到的另外一个面试题那就是和let和const相关的知识点,这个知识点可以说就是为了减少内存泄露的场景而创造的
下面全局作用域中声明了一个全局变量,并且赋值了一个大对象,如果不做删除引用,那么这对象将一直存在,除非页面关闭了,这种大对象会导致内存消耗变大,尤其是在长时间运行的单页应用中
javascript
// 全局变量示例
window.globalVariable = { /* 大对象 */ };
// 全局变量将一直存在,直到页面卸载
// 避免使用全局变量,尽量将变量限制在局部作用域中
如果是声明了全局变量,那么该变量将会一直存在直到页面卸载,我们应该尽量减少对全局变量的引用,或者不再需要全局变量时,将其设置为 null
DOM 引用

使用document.getElementById等获取dom元素的方法,会将获取到的元素保存到变量中,如果获取完没有清除

ini
// DOM 引用示例
const element = document.getElementById('myElement');
// 如果忘记清除引用,它将一直存在,即使元素被删除
// element = null; // 应当清除引用或使用 removeChild 从 DOM 中删除元素
解决方法:确保在不再需要 DOM 元素引用时,将其设置为 null
或使用 removeChild
从 DOM 中删除元素。
大型数据结构
在应用程序中使用大型数据结构(如缓存)时,如果不管理好数据的生命周期,可能导致内存泄漏。定期清理或过期数据是一种避免这种类型的内存泄漏的方法。
比如下面这种大数组,在创建的时候就要考虑后续如果不需要用到的时候应该记得把内存释放出来,不然占用内存也是一种内存泄漏的表现
js
// 创建一个大数组
const bigArray = new Array(1000000).fill(0);
// 在不再需要大数组时,设置为 null 释放内存 bigArray = null;
不合理的递归
无限递归调用可能导致栈溢出,这也可以被视为一种内存泄漏。确保递归函数有终止条件,以防止无限递归。
可以看到下面这函数没有一个终止的条件,也可以说是一个死循环
js
function fibonacci(n) {
if (n <= 0) {
return 0;
}
return fibonacci(n - 1) + fibonacci(n - 2); // 缺乏终止条件
}
const result = fibonacci(10);
console.log(result);
闭包
闭包算是一个比较常见的面试问题了,有些面试官喜欢从闭包问到内存泄漏,基本上这么多的面试中,只要面试官问了我有关闭包的问题,我就会回答导致内存泄漏,这样面试官会顺着你的答案继续深问,会问你内存泄漏的场景,这也是一个面试的小技巧,把关联的面试题都串起来。
javascript
javascriptCopy code
function leakMemory() {
const data = new Array(1000000); // 创建一个大型数组
return function () {
// 这个函数形成了闭包,保留对 data 变量的引用
console.log(data[0]); // 使用数组中的数据
};
}
以上就是一个典型的一个闭包,可以看到包含了大型的数据,返回了一个闭包函数,这就会导致内存泄漏,因为垃圾回收器无法释放data中的内存,如果时间久了,没有被消除引用的内存占用就会越来越多,从而导致页面的进程奔溃并且十分卡顿和缓慢
总结
说到底,内存泄漏的场景有很多,但是解决的方法都是大同小异,需要我们去消除一些没有用到的内存,如果没有释放,就会导致内存占用过多导致堆积,内存泄漏也就是这么来的。