JS造成内存泄漏的几种情况实例分析


Posted in Javascript onMarch 02, 2020

本文实例讲述了JS造成内存泄漏的几种情况。分享给大家供大家参考,具体如下:

介绍:

js中的内存垃圾回收机制:垃圾回收器会定期扫描内存,当某个内存中的值被引用为零时就会将其回收。当前变量已经使用完毕但依然被引用,导致垃圾回收器无法回收这就造成了内存泄漏。传统页面每次跳转都会释放内存,所以并不是特别明显。

Vue单页面应用中:Web App 与 传统Web的区别,因为Web App是单页面应用页面通过路由跳转不会刷新页面,导致内存泄漏不断堆积,导致页面卡顿。

泄漏点:

1.DOM/BOM 对象泄漏
2.script 中存在对DOM/BOM 对象的引用导致
3.Javascript 对象泄漏
4.通常由闭包导致,比如事件处理回调,导致DOM对象和脚本中对象双向引用,这个时常见的泄漏原因

代码关注点:

1.DOM中的addEventLisner 函数及派生的事件监听, 比如Jquery 中的on 函数, vue 组件实例的 $on 函数,第三方库中的初始化函数
2.其它BOM对象的事件监听, 比如websocket 实例的on 函数
3.避免不必要的函数引用
4.如果使用render 函数,避免在html标签中绑定DOM/BOM 事件

Vue如何处理:

1.如果在mounted/created 钩子中绑定了DOM/BOM 对象中的事件,需要在beforeDestroy 中做对应解绑处理
2.如果在mounted/created 钩子中使用了第三方库初始化,需要在beforeDestroy 中做对应销毁处理
3.如果组件中使用了定时器,需要在beforeDestroy 中做对应销毁处理
4.模板中不要使用表达式来绑定到特定的处理函数,这个逻辑应该放在处理函数中?
5.如果在mounted/created 钩子中使用了$on,需要在beforeDestroy 中做对应解绑($off)处理
6.某些组件在模板中使用 事件绑定可能会出现泄漏,使用$on 替换模板中的绑定

Vue官网讲解避免内存泄露https://cn.vuejs.org/v2/cookbook/avoiding-memory-leaks.html

另外,vue  在IE edge浏览器下,父子组件的场景,子组件依赖父组件的状态,子组件控制父组件状态变化从而反馈给子组件的展示变化,子组件通过v-if模式存在于视图中,父组件通过状态控制子组件的v-if状态变换。子组件控制父组件状态完成子组件数据填充后,父组件切换子组件的v-if状态,子组件占用dom结构被清理。此时,子组件存在时的内存占用未被释放,当父组件再次回切v-if状态时,子组件重新展示,内存飙升,重复几次切换后,内存飙升明显,页面卡顿。

js通常内存泄漏的几种情况的介绍

1.闭包

function fn1(){
  var n=1;
}
//我想取到里面的局部变量n
function fn1(){
  var n=1;
  function fn2(){//在加一个fn2当他的子集
    alert(n);
  }
 
}

但是我在外面还是访问不到那就return出来 

function fn1(){
  var n=1;
  function fn2(){//在加一个fn2当他的子集
    alert(n);
  }
return fn2(); 
//return出来后 他就给 window了所以一直存在内存中。因为一直在内存中,在IE里容易造成内存泄漏
}
fn1();

尽量书写的时候,避免这种情况。 

2.意外的全局变量 

一个未声明变量的引用会在全局对象中创建一个新的变量。在浏览器的环境下,全局对象就是 window,也就是说:

function foo(arg) {
  bar = "aaaaa";
}
 
实际上等价于
function foo(arg) {
  window.bar = "aaaaa";
}
function foo() {
  this.variable = "qqqqq";
}
//this 指向全局对象(window)
foo();

 为了防止这种错误的发生,可以在你的 JavaScript 文件开头添加 'use strict'; 语句

3.定时器setTimeout setInterval

当不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。比如:vue使用了定时器,需要在beforeDestroy 中做对应销毁处理。js也是一样的。

clearTimeout(***)
clearInterval(***)

4.如果在mounted/created 钩子中使用了$on,需要在beforeDestroy 中做对应解绑($off)处理

beforeDestroy() {
 this.bus.$off('****');
}

5、给DOM对象添加的属性是一个对象的引用

var testObject = {}; 
document.getElementById('idname').property = testObject; //如果DOM不被消除,则testObject会一直存在,造成内存泄漏

解决方法:

在window.onunload事件中写上:

window.onunload=function(){
  document.getElementById('idname').property = null;     //释放内存
};

6.DOM对象与JS对象相互引用

function testObject(element) { 
this.elementReference = element;   // 为testObject(js)对象的属性绑定element(DOM)对象
element.property = this;    // 为element(DOM)对象的属性绑定testObject(js)对象
} 
new testObject(document.getElementById('idname'));

解决方法:

在window.onunload事件中写上:

document.getElementById('idname').property = null;

7.从外到内执行appendChild。这时即使调用removeChild也无法释放

var parentDiv = document.createElement("div"); 
var childDiv = document.createElement("div"); 
document.body.appendChild(parentDiv); 
parentDiv.appendChild(childDiv);

解决方法: 
从内到外执行appendChild: 

var parentDiv = document.createElement("div"); 
var childDiv = document.createElement("div"); 
parentDiv.appendChild(childDiv); 
document.body.appendChild(parentDiv); 

8.反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)

for(i = 0; i < 5000; i++) { 
  hostElement.text = "asdfasdfasdf"; 
}

这种方式相当于定义了5000个属性! 

9.注意程序逻辑,避免“死循环”之类的

10.echarts配合循环计时器等出现的内存泄漏

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript操作DOM技巧总结》、《JavaScript页面元素操作技巧总结》、《JavaScript事件相关操作与技巧大全》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
Jquery中的层次选择器与find()的区别示例介绍
Feb 20 Javascript
javascript检测浏览器的缩放状态实现代码
Sep 28 Javascript
jQuery实现的给图片点赞+1动画效果(附在线演示及demo源码下载)
Dec 31 Javascript
HTML Table 空白单元格补全的简单实现
Oct 13 Javascript
微信小程序 本地数据存储实例详解
Apr 13 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
Sep 11 Javascript
浅谈SpringMVC中post checkbox 多选框value的值(隐藏域方式)
Jan 08 Javascript
解决vue点击控制单个样式的问题
Sep 05 Javascript
详解vue数组遍历方法forEach和map的原理解析和实际应用
Nov 15 Javascript
Flutter实现仿微信底部菜单栏功能
Sep 18 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
May 08 Javascript
Vue 数据响应式相关总结
Jan 28 Vue.js
JavaScript HTML DOM 元素 (节点)新增,编辑,删除操作实例分析
Mar 02 #Javascript
JavaScript中break、continue和return的用法区别实例分析
Mar 02 #Javascript
Vue Router的手写实现方法实现
Mar 02 #Javascript
ES6中Set和Map用法实例详解
Mar 02 #Javascript
Vue父组件向子组件传值以及data和props的区别详解
Mar 02 #Javascript
js中addEventListener()与removeEventListener()用法案例分析
Mar 02 #Javascript
js构造函数constructor和原型prototype原理与用法实例分析
Mar 02 #Javascript
You might like
PHP配置ZendOpcache插件加速
2019/02/14 PHP
文字幻灯片
2006/06/26 Javascript
javascript中如何处理引号编码&amp;#034;
2013/08/15 Javascript
利用jQuery简单实现产品展示图片左右滚动功能(示例代码)
2014/01/02 Javascript
javascript实现避免页面按钮重复提交
2015/01/08 Javascript
jquery动态添加删除(tr/td)
2015/02/09 Javascript
全面解析Bootstrap排版使用方法(文字样式)
2015/11/30 Javascript
Javascript获取数组中的最大值和最小值的方法汇总
2016/01/01 Javascript
JQuery DIV 动态隐藏和显示的方法
2016/06/23 Javascript
js重写方法的简单实现
2016/07/10 Javascript
关于JS中二维数组的声明方法
2016/09/24 Javascript
jQuery实现手机版页面翻页效果的简单实例
2016/10/05 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
Vue-cli-webpack搭建斗鱼直播步骤详解
2017/11/17 Javascript
关于Angularjs中自定义指令一些有价值的细节和技巧小结
2018/04/22 Javascript
基于vue实现探探滑动组件功能
2020/05/29 Javascript
[02:12]探秘2016国际邀请赛中国区预选赛选手房间
2016/06/25 DOTA
[32:07]完美世界DOTA2联赛PWL S3 LBZS vs Rebirth 第一场 12.16
2020/12/17 DOTA
python转换摩斯密码示例
2014/02/16 Python
Python中使用item()方法遍历字典的例子
2014/08/26 Python
用python读写excel的方法
2014/11/18 Python
在Python操作时间和日期之asctime()方法的使用
2015/05/22 Python
删除DataFrame中值全为NaN或者包含有NaN的列或行方法
2018/11/06 Python
python 计算两个列表的相关系数的实现
2019/08/29 Python
布隆过滤器的概述及Python实现方法
2019/12/08 Python
TensorFLow 不同大小图片的TFrecords存取实例
2020/01/20 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
2020/05/26 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
特色蛋糕店创业计划书
2014/01/28 职场文书
关于母亲节的感言
2014/02/04 职场文书
网络编辑岗位职责
2014/03/18 职场文书
应聘英语教师求职信
2014/04/24 职场文书
承诺书格式范文
2014/06/03 职场文书
授权委托书
2014/07/31 职场文书
2014年秋季新学期寄语
2014/08/02 职场文书
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python