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 相关文章推荐
javascript实现的DES加密示例
Oct 30 Javascript
javascript新建标签,判断键盘输入,以及判断焦点(示例代码)
Nov 25 Javascript
js的[defer]和[async]属性
Nov 24 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
Sep 02 Javascript
javascript运算符——位运算符全面介绍
Jul 14 Javascript
js html5 css俄罗斯方块游戏再现
Oct 17 Javascript
vue-router3.0版本中 router.push 不能刷新页面的问题
May 10 Javascript
Vuex持久化插件(vuex-persistedstate)解决刷新数据消失的问题
Apr 16 Javascript
Vue中util的工具函数实例详解
Jul 08 Javascript
小程序如何在不同设备上自适应生成海报的实现方法
Aug 20 Javascript
js实现登录时记住密码的方法分析
Apr 05 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 Javascript
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
编译问题
2006/10/09 PHP
php统计数组元素个数的方法
2015/07/02 PHP
PHP使用MPDF类生成PDF的方法
2015/12/08 PHP
php获取文件后缀的9种方法
2016/03/22 PHP
PHP生成图像验证码的方法小结(2种方法)
2016/07/18 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
PHP程序守护进程化实现方法详解
2020/07/16 PHP
由prototype_1.3.1进入javascript殿堂-类的初探
2006/11/06 Javascript
setTimeout函数兼容各主流浏览器运行执行效果实例
2013/06/13 Javascript
jQuery中fadeOut()方法用法实例
2014/12/24 Javascript
jquery小火箭返回顶部代码分享
2015/08/19 Javascript
js实现仿京东2级菜单效果(带延时功能)
2015/08/27 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
2015/09/26 Javascript
jquery调整表格行tr上下顺序实例讲解
2016/01/09 Javascript
node.js实现登录注册页面
2017/04/08 Javascript
完美解决axios在ie下的兼容性问题
2018/03/05 Javascript
JavaScript解析及序列化JSON的方法实例分析
2019/01/04 Javascript
Vue 中如何正确引入第三方模块的方法步骤
2019/05/05 Javascript
socket在egg中的使用实例代码详解
2019/05/30 Javascript
详解微信小程序图片地扯转base64解决方案
2019/08/18 Javascript
Layui表格行工具事件与数据回填方法
2019/09/13 Javascript
[01:04:01]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第一场
2014/05/24 DOTA
使用Python解析JSON数据的基本方法
2015/10/15 Python
Python实现自动添加脚本头信息的示例代码
2016/09/02 Python
django请求返回不同的类型图片json,xml,html的实例
2018/05/22 Python
Python 访问限制 private public的详细介绍
2018/10/16 Python
对Python中的条件判断、循环以及循环的终止方法详解
2019/02/08 Python
Python如何实现邮件功能
2020/05/27 Python
Pandas之缺失数据的实现
2021/01/06 Python
使用html5 canvas绘制圆环动效
2019/06/03 HTML / CSS
加拿大时装零售商:Influence U
2018/12/22 全球购物
汽车机修工岗位职责
2014/03/06 职场文书
小学生推普周国旗下讲话稿
2014/09/21 职场文书
2015年初中生自我评价范文
2015/03/03 职场文书
2015年社区精神文明工作总结
2015/05/26 职场文书
活动宣传稿范文
2015/07/23 职场文书