前言
本系列最开始是为了自己面试准备的.后来发现整理越来越多,差不多有十二万字符,最后决定还是分享出来给大家.
为了分享整理出来,花费了自己大量的时间,起码是只自己用的三倍时间.如果喜欢的话,欢迎收藏,关注我!谢谢!
文章链接
- 前端面试查漏补缺--(一) 防抖和节流
- 前端面试查漏补缺--(二) 垃圾回收机制
- 前端面试查漏补缺--(三) 跨域及常见解决办法
- 前端面试查漏补缺--(四) 前端本地存储
- 前端面试查漏补缺--(五) 渲染机制及重绘和回流
- 前端面试查漏补缺--(六) 浏览器缓存
- 前端面试查漏补缺--(七) XSS攻击与CSRF攻击
- 前端面试查漏补缺--(八) 前端加密
- 前端面试查漏补缺--(九) HTTP与HTTPS
- 前端面试查漏补缺--(十) 前端鉴权
- 前端面试查漏补缺--(十一) 前端软件架构模式MVC/MVP/MVVM
- 前端面试查漏补缺--(十二) 从输入URL到看到页面发生的全过程(含三握手,四挥手详解)
- 前端面试查漏补缺--(十三) 内存泄漏
- 前端面试查漏补缺--(十四) 算法及排序
- 前端面试查漏补缺--(十五) Event Loop
合集篇:
前端面试查漏补缺--Index篇(12万字符合集) 包含目前已写好的系列其他十几篇文章.后续新增值文章不会再在每篇添加链接,强烈建议议点赞,关注合集篇!!!!,谢谢!~
后续更新计划
后续还会继续添加设计模式,前端工程化,项目流程,部署,闭环,vue常考知识点 等内容.如果觉得内容不错的话欢迎收藏,关注我!谢谢!
求一份内推
目前本人也在准备跳槽,希望各位大佬和HR小姐姐可以内推一份靠谱的武汉 前端岗位!邮箱:[email protected].谢谢啦!~
什么是内存泄漏?
程序的运行需要内存。只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存。
对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能:变慢,延迟大等 ,重则导致进程崩溃。
不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
内存泄漏的识别方法
-
使用快捷键
F12
或者Ctrl+Shift+J
打开 Chrome 浏览器的「开发者工具」。 -
选择
Performance
(老版为Timeline) 选项卡,在Capture
选项中,只勾选Memory
。 -
设置完成后,点击最左边的
Record
按钮,然后就可以访问网页了。 -
打开一个网站,例如:www.taobao.com,当网页加载完成后,点击
Stop
,等待分析结果。 -
然后在
Chart View
上寻找内存急速下降的部分,查看对应的Event Log
,可以从中找到 GC 的日志。
具体过程如下图所示:
内存泄露的常见原因及处理方式
常见原因:
1. 意外的全局变量
下面代码中变量bar在foo函数内,但是bar并没有声明.JS就会默认将它变为全局变量,这样在页面关闭之前都不会被释放.
function foo(){
bar=2
console.log('bar没有被声明!')
}
复制代码
b 没被声明,会变成一个全局变量,在页面关闭之前不会被释放.使用严格模式可以避免.
2. dom清空时,还存在引用
很多时候,为了方便存取,经常会将 DOM 结点暂时存储到数据结构中.但是在不需要该DOM节点时,忘记解除对它的引用,则会造成内存泄露.
var element = {
shotCat: document.getElementById('shotCat')
};
document.body.removeChild(document.getElementById('shotCat'));
// 如果element没有被回收,这里移除了 shotCat 节点也是没用的,shotCat 节点依然留存在内存中.
复制代码
与此类似情景还有: DOM 节点绑定了事件, 但是在移除的时候没有解除事件绑定,那么仅仅移除 DOM 节点也是没用的
3. 定时器中的内存泄漏
var someResource = getData();
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
node.innerHTML = JSON.stringify(someResource));
}
}, 1000);
复制代码
如果没有清除定时器,那么 someResource 就不会被释放,如果刚好它又占用了较大内存,就会引发性能问题. 但是 setTimeout ,它计时结束后它的回调里面引用的对象占用的内存是可以被回收的. 当然有些场景 setTimeout 的计时可能很长, 这样的情况下也是需要纳入考虑的.
4. 不规范地使用闭包
例如下面的例子: 相互循环引用.这是经常容易犯的错误,并且有时也不容易发现.
function foo() {
var a = {};
function bar() {
console.log(a);
};
a.fn = bar;
return bar;
};
复制代码
bar和a形成了相互循环引用.可能有人说bar里不使用console.log(a)不就没有引用了吗就不会造成内存泄露了.NONONO,bar作为一个闭包,即使它内部什么都没有,foo中的所有变量都还是隐式地被 bar所引用。 即使bar内什么都没有还是造成了循环引用,那真正的解决办法就是,不要将a.fn = bar.
避免策略:
- 减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收(即赋值为null);
- 注意程序逻辑,避免“死循环”之类的 ;
- 避免创建过多的对象 原则:不用了的东西要记得及时归还。
- 减少层级过多的引用
Node中的内存泄漏
node中的内存泄露与JS中的处理方法稍有不同,详细可以查看这篇文章,非常的详细!
感谢及参考
- JavaScript 内存泄漏教程
- V8的垃圾回收机制