search
HomeBackend DevelopmentPython TutorialJavaScript 闭包都会内存泄露吗?

最近看了一些 JavaScript 的内存泄露问题,看似没问题的代码原来存在内存泄露,而且部分还不知道怎么回事,比如:

<span class="kd">function</span> <span class="p">(</span><span class="nx">element</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
	<span class="nx">element</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
		<span class="c1">//TODO a b here</span>
	<span class="p">}</span>
<span class="p">}</span>

回复内容:

这个不叫「内存泄漏」。

这个代码运行之后,只要 element 不再被引用,a、b 也会被回收。题主的意图估计是希望 a、b 的生命周期比 element 短。那是你的设计错误。因为你把 element 的一个 event-handler 设计成依赖于 a、b,那 a、b 当然就要和 element 共生死了。题主给的这个逻辑用不用闭包都会有这个问题。如果硬要释放 a、b,那就是 release before use,会造成 null-dereference error。 很多资料都过时了,内存泄露这个点在js圈子里更多的是惯性而不是实际影响。一般情况下,不用担心那么多,浏览器有自己的垃圾回收机制,只要你不作死把所有不再需要的资源都放到某个永远不会释放的数组什么的里面就好。遇到具体的内存泄露问题再具体解决。
<span class="kd">var</span> <span class="nx">test_obj</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nx">closure_fn</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
        <span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> 
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'Rambo!'</span><span class="p">);</span> 
            <span class="nx">that</span><span class="p">.</span><span class="nx">closure_fn</span><span class="p">();</span>
        <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">};</span>
<span class="nx">test_obj</span><span class="p">.</span><span class="nx">closure_fn</span><span class="p">();</span>
<span class="nx">test_obj</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">// 尝试之后,你会发现这他妈才是可怕的。</span>

<span class="kd">var</span> <span class="nx">test_obj_2</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nx">closure_fn</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="nx">test_obj_2</span><span class="p">;</span>
        <span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> 
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'Rambo!'</span><span class="p">);</span> 
            <span class="nx">that</span> <span class="o">?</span> <span class="nx">that</span><span class="p">.</span><span class="nx">closure_fn</span><span class="p">()</span> <span class="o">:</span> <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">val</span><span class="p">);</span>
        <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">};</span>
我记得 @贺师俊 老师在ITEYE上有过一段关于这个的讨论。

首先,这是一个闭包。

题主贴的代码里之所以造成内存泄露是因为循环引用。一个闭包在创建时会附有三个属性:VO、thisValue、scope chain,而其中scope chain是指向外层parent scope的引用。

因此这个闭包实际上保存了外层函数中element的引用,而element本身又引用了闭包,循环引用因此而见。

但是我记得hax同时提到,因为循环引用导致的泄露实际上是IE浏览器引擎的bug而导致的,而如果element不是dom对象,不产生循环引用也就不会leak了。 这个不好说,有可能会泄露吧。。 我也有话说:
首先,IE9之前的版本因为对JScript对象和COM对象使用不同的垃圾收集机制,因此才有机会出现这个问题。再者,闭包的作用域链中保存着html元素,且包含循环引用。第三,取消循环引用并置空引用的html元素就可有效避免 仅供参考,未作过实验验证(附近确实找不到装IE6和IE7的机器了):

据微软称这是IE6在XP上特有的问题,照下面这篇最后更新日期为2011年10月的kb文章
A memory leak occurs in Internet Explorer 6 when you view a Web page that uses JScript scripting on a Windows XP-based computer
的说法,如果你的系统包含了这个更新:
support.microsoft.com/k
就没有这个问题了。 其实我很好奇的是,闭包,在什么情况下才会真的造成内存泄漏呢?
或许是我代码写少了,真的重来没有过内存泄漏的时候... 首先,题主问的闭包是否都会内存泄露,这个可以明确说不是。题主贴的代码产生了内存泄露是因为循环引用。低版本ie对这种循环引用的处理有bug,会造成内存泄露。
想要避免泄露,应该break circle。让element = null。这样handler就不持有dom的引用了。 内存泄漏和内存使用这两个概念搞清楚?
Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
element.style怎么修改element.style怎么修改Nov 24, 2023 am 11:15 AM

element.style修改元素的方法:1、修改元素的背景颜色;2、修改元素的字体大小;3、修改元素的边框样式;4、修改元素的字体样式;5、修改元素的水平对齐方式。详细介绍:1、修改元素的背景颜色,其语法为“document.getElementById("myElement").style.backgroundColor = "red";”;2、修改元素的字体大小等等。

function是什么意思function是什么意思Aug 04, 2023 am 10:33 AM

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果,其目的是封装一段可重复使用的代码,提高代码的可重用性和可维护性。

es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

"enumerate()"函数在Python中的用途是什么?"enumerate()"函数在Python中的用途是什么?Sep 01, 2023 am 11:29 AM

在本文中,我们将了解enumerate()函数以及Python中“enumerate()”函数的用途。什么是enumerate()函数?Python的enumerate()函数接受数据集合作为参数并返回一个枚举对象。枚举对象以键值对的形式返回。key是每个item对应的索引,value是items。语法enumerate(iterable,start)参数iterable-传入的数据集合可以作为枚举对象返回,称为iterablestart-顾名思义,枚举对象的起始索引由start定义。如果我们忽

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

Hot Tools

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software