当前位置: 首页 > news >正文

JS中4种常见的内存泄漏

一、什么是内存泄漏

本质上讲,内存泄漏是当一块内存不再被应用程序使用的时候,由于某种原因,这块内存没有返还给操作系统或空闲内存池的现象。

二、几种常见的内存泄漏

1、意外的全局变量

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

function foo(arg) {
    bar = "this is a hidden global variable";
}

实际上是:

function foo(arg) {
    window.bar = "this is an explicit global variable";
}

上面代码中,如果bar是一个应该指向foo函数作用域内变量的引用,但忘记使用var来声明这个变量,这时就相当于创建了一个全局变量。

另外一种偶然创建全局变量的方式如下:

function foo() {
    this.variable = "potential accidental global";
} 
foo();

上面代码中,foo函数再全局作用域中被调用,因此this指向window

全局变量的注意事项:

如果需要全局变量来存储很多数据,必须确保在使用过后将它设置为null或重新为他赋值。

常见的和全局变量相关的引发内存消耗增长的原因是缓存。缓存存储着可复用的数据。

为了让这种做法更高效,必须为缓存的容量规定一个上界。由于缓存不能被及时回收的缘故,缓存无限制地增长会导致很高的内存消耗。

2、闭包引起的内存泄漏

闭包可以使变量常驻内存,但如果使用不当就会在成内存泄漏

var theThing = null;
var replaceThing = function () {
  var originalThing = theThing;
  var unused = function () {
    if (originalThing)
      console.log("hi");
  };
  theThing = {
    longStr: new Array(1000000).join('*'),
    someMethod: function () {
      console.log(someMessage);
    }
  };
};
setInterval(replaceThing, 1000);

上面代码中,每次调用 replaceThing 时,theThing 都会得到新的包含一个大数组和新的闭包(someMethod)的对象。

同时,没有用到的那个变量持有一个引用了 originalThingreplaceThing 调用之前的 theThing)闭包。

关键的问题是每当在同一个父作用域下创建闭包作用域的时候,这个作用域是被共享的。在这种情况下,someMethod 的闭包作用域和 unused 的作用域是共享的。

unused 持有一个 originalThing 的引用。尽管 unused 从来没有被使用过,someMethod 可以在 theThing 之外被访问。

而且 someMethod 和 unused 共享了闭包作用域,即便 unused 从来都没有被使用过,它对 originalThing 的引用还是强制它保持活跃状态(阻止它被回收)。

当这段代码重复运行时,将可以观察到内存消耗稳定地上涨,并且不会因为 GC 的存在而下降。

本质上来讲,创建了一个闭包链表(根节点是 theThing 形式的变量),而且每个闭包作用域都持有一个对大数组的间接引用,这导致了一个巨大的内存泄露。

3、DOM之外的引用

var elements={  
    button: document.getElementById("button"),  
    image: document.getElementById("image"),  
    text: document.getElementById("text")  
};  
function doStuff(){  
    image.src="http://some.url/image";  
    button.click():  
    console.log(text.innerHTML)  
}  
function removeButton(){  
    document.body.removeChild(document.getElementById('button'))  
}  

2、被遗漏的定时器和回调函数

var someResouce=getData();  
setInterval(function(){  
    var node=document.getElementById('Node');  
    if(node){  
        node.innerHTML=JSON.stringify(someResouce)  
    }  
},1000) 

上面代码中, 如果 id 为 Node 的元素从 DOM 中移除, 该定时器仍会存在, 同时, 因为回调函数中包含对 someResource 的引用, 定时器外面的 someResource 也不会被释放。

三、怎样避免内存泄漏

1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

2)注意程序逻辑,避免“死循环”之类的 ;

3)避免创建过多的对象  原则:不用了的东西要及时归还。

相关文章:

  • 详解Shiro认证流程
  • 金山办公:订阅为王?
  • 【JavaEE】Spring AOP (面向切面)详解
  • java基于ssm的快递物流管理系统
  • SETTLE约束算法中的坐标变换问题
  • 基于python的家政管理系统毕业设计源码071111
  • SpringBoot基础篇 (3)——基础配置
  • springboot基于web的在线问答社区系统设计与实现毕业设计源码061628
  • 神经网络的基本思路包括,神经网络的基本思路是
  • CREO:CREO软件之工程图【创建】以及配置(符合国家标准)的简介及其使用方法(图文教程)之详细攻略
  • Windows与网络基础-4-安装GNS3软件环境
  • 长安链源码学习v2.2.1--ioc机制(十)
  • 前端工作小结33-确定需求报告
  • SpringMVC 01: SpringMVC + 第一个SpringMVC项目
  • js之原生ajax、Jquery-$.ajax、自定义ajax(post请求、get请求)
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Apache的80端口被占用以及访问时报错403
  • Docker容器管理
  • emacs初体验
  • Redis在Web项目中的应用与实践
  • 动态规划入门(以爬楼梯为例)
  • 对超线程几个不同角度的解释
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 力扣(LeetCode)357
  • 前端相关框架总和
  • 深度解析利用ES6进行Promise封装总结
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​Spring Boot 分片上传文件
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​如何在iOS手机上查看应用日志
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • (定时器/计数器)中断系统(详解与使用)
  • (动态规划)5. 最长回文子串 java解决
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十)c52学习之旅-定时器实验
  • (一一四)第九章编程练习
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转载)从 Java 代码到 Java 堆
  • **PHP分步表单提交思路(分页表单提交)
  • .Net Winform开发笔记(一)
  • .Net的DataSet直接与SQL2005交互
  • .net连接oracle数据库
  • .set 数据导入matlab,设置变量导入选项 - MATLAB setvaropts - MathWorks 中国
  • :“Failed to access IIS metabase”解决方法
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @TableLogic注解说明,以及对增删改查的影响
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [ C++ ] STL---string类的模拟实现
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [Android]使用Retrofit进行网络请求
  • [BIZ] - 1.金融交易系统特点
  • [BT]小迪安全2023学习笔记(第15天:PHP开发-登录验证)
  • [bzoj1901]: Zju2112 Dynamic Rankings