前言

内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。这里就讲一些常见会带来内存泄露的原因。

0. 全局变量

JavaScript自由的其中一种方式是它可以处理没有声明的变量:一个未声明的变量的引用在全局对象中创建了一个新变量。在浏览器的环境中,全局对象是window。
 function foo(){
name = '前端曰';
}
// 其实是把name变量挂载在window对象上
function foo(){
window.name = '前端曰';
} // 又或者
function foo(){
this.name = '前端曰';
}
foo() // 其实这里的this就是指向的window对象

这样无意中一个意外的全局变量就被创建了,为了阻止这种错误发生,在你的Javascript文件最前面添加 'use strict;' 。这开启了解析JavaScript的阻止意外全局的更严格的模式。或者自己注意好变量的定义!

1. 循环引用

在js的内存管理环境中,对象 A 如果有访问对象 B 的权限,叫做对象 A 引用对象 B。引用计数的策略是将“对象是否不再需要”简化成“对象有没有其他对象引用到它”,如果没有对象引用这个对象,那么这个对象将会被回收 。

 function func() {
let obj1 = {};
let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2
obj2.a = obj1; // obj2 引用 obj1
}

当函数 func 执行结束后,返回值为 undefined,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1 和 obj2 的引用次数都不为 0,所以他们不会被回收。要解决循环引用的问题,最好是在不使用它们的时候手工将它们设为空。

解决方案:obj1 和 obj2 都设为 null 。

2. 闭包

闭包:匿名函数可以访问父级作用域的变量。

 var names = (function(){
var name = 'js-say';
return function(){
console.log(name);
}
})()

闭包会造成对象引用的生命周期脱离当前函数的上下文,如果闭包如果使用不当,可以导致环形引用(circular reference),类似于死锁,只能避免,无法发生之后解决,即使有垃圾回收也还是会内存泄露。

3. 被遗忘的延时器/定时器

在我们的日常需求中,可能会经常试用到 setInterval/setTimeout ,但是使用完之后通常忘记清理。

 var someResource = getData();
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
// 处理 node 和 someResource
node.innerHTML = JSON.stringify(someResource));
}
}, );

setInterval/setTimeout 中的 this 指向的是window对象,所以内部定义的变量也挂载到了全局;if 内引用了 someResource 变量,如果没有清除 setInterval/setTimeout 的话someResource 也得不到释放;同理其实 setTimeout也一样。所以我们用完需要记得去 clearInterval/clearTimeout

4. DOM引起的内存泄露

  • 未清除DOM引用
 var refA = document.getElementById('refA');
document.body.removeChild(refA);
// #refA不能回收,因为存在变量refA对它的引用。将其对#refA引用释放,但还是无法回收#refA。

解决方案:refA = null 。

  • DOM对象添加的属性是一个对象的引用
var MyObject = {};
document.getElementById('myDiv').myProp = MyObject;

解决方案:在页面 onunload 事件中释放 document.getElementById('myDiv').myProp = null; 

DOM被删除或清空没有清楚绑定事件这种情况应该是比较常见的,同时也应该是比较容易被忽略的。

  • 给DOM对象绑定事件
 var btn = document.getElementById("myBtn");
btn.onclick = function(){
document.getElementById("myDiv").innerHTML = "wechat: js-say";
} document.body.removeChild(btn);
btn = null;

这里把DOM移除了,但是绑定的事件仍没被移除,会引起内存泄露所以需要清除事件。

 var btn = document.getElementById("myBtn");
btn.onclick = function(){
btn.onclick = null;
document.getElementById("myDiv").innerHTML = "wechat: js-say";
} document.body.removeChild(btn);
btn = null;

常见的Java Script内存泄露原因及解决方案的更多相关文章

  1. java造成内存泄露原因

    一.Java内存回收机制  不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(He ...

  2. Java内存泄露原因详解

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的, 这些对象的创建都是在堆(He ...

  3. java中内存泄露有几种?如何分析泄露原因

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Hea ...

  4. .Net内存泄露原因及解决办法

    .Net内存泄露原因及解决办法 1.    什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...

  5. 解决Net内存泄露原因

    Net内存泄露原因及解决办法 https://blog.csdn.net/changtianshuiyue/article/details/52443821 什么是.Net内存泄露 (1).NET 应 ...

  6. java的内存泄露是如何发生的,如何避免和发现

    java的垃圾回收与内存泄露的关系:[新手可忽略不影响继续学习] 马克-to-win:上一节讲了,(i)对象被置成null.(ii)局部对象(无需置成null)当程序运行到右大括号.(iii)匿名对象 ...

  7. Java的内存泄露

    Java的内存泄露 1.静态集合类引起内存泄漏 像HashMap.Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们 ...

  8. Android开发笔记——常见BUG类型之内存泄露与线程安全

    本文内容来源于最近一次内部分享的总结,没来得及详细整理,见谅. 本次分享主要对内存泄露和线程安全这两个问题进行一些说明,内部代码扫描发现的BUG大致分为四类:1)空指针:2)除0:3)内存.资源泄露: ...

  9. 记一次Java的内存泄露分析

    当前环境 jdk == 1.8 httpasyncclient == 4.1.3 代码地址 git 地址:https://github.com/jasonGeng88/java-network-pro ...

随机推荐

  1. Python使用Flask框架,结合Highchart处理jsonl数据

    1.html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. ubuntu_linux自动补全出现问题

    问题:输入: cd p,使用Tab补全,期望进入pub_work目录,虽然自动补全,成功进入目录:却给我打印一连串的字符,纠结: fly@Flyme:~$ cd p+ local cur prev w ...

  3. 洛谷 1328 生活大爆炸版石头剪刀布(NOIp2014提高组)

    [题解] 简单粗暴的模拟题. #include<cstdio> #include<algorithm> #include<cstring> #define LL l ...

  4. 洛谷P1028数的计算

    https://www.luogu.org/problemnew/show/P1028 只用递归会超时,需要用递归型动规,用一个数组保存已经算过的值,避免重复计算. 求数字为n的方案数的最优子结构为: ...

  5. noip模拟赛 小Y的问题

    [问题描述]有个孩子叫小 Y,一天,小 Y 拿到了一个包含 n 个点和 n-1 条边的无向连通图, 图中的点用 1~n 的整数编号.小 Y 突发奇想,想要数出图中有多少个“Y 字形”.一个“Y 字形” ...

  6. Prime Land(poj 1365)

    题意:这题题意难懂,看了题解才知道的.比如第二组sample,就是5^1*2^1=10, 求10-1即9的质因数分解,从大到小输出,即3^2.本来很简单的嘿,直接最快速幂+暴力最裸的就行了. #inc ...

  7. windows开启3306端口并用可视化工具访问远程mysql(授权访问)

    开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 3306 端口,否则远程是无法通过 330 ...

  8. Spark之安装和使用

    Scala安装 Spark使用Scala开发,安装的Scala版本必须和Spark使用的版本一致,否则使用Scala编写的Spark任务会有兼容性问题 可以到Spark官网查看确定Scala版本,或者 ...

  9. fastjson将java list转为json字符串

    1.直接用fastjson的静态方法string JSON.toJSONString(list)方法就行,JSON.toJSONString(list)将java list转为json字符串. 2.t ...

  10. 【Android 开发实例】时间管理APP开发之数据库设计

    当然也能够先写界面什么的.可是,总认为先把数据库后台写好在写界面比較放心. 对于数据库的设计,我一開始没什么概念.甚至不知道怎样下手,一開始想着设计成几个表?有哪些字段? 最后用了两天时间,还是一无所 ...