分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

JS中4种常见的内存泄漏

发布时间:2023-09-06 01:47责任编辑:苏小强关键词:暂无标签

一、什么是内存泄漏

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

二、几种常见的内存泄漏

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)避免创建过多的对象  原则:不用了的东西要及时归还。

JS中4种常见的内存泄漏

原文地址:https://www.cnblogs.com/endlessmy/p/8688056.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved