検索

最近看了一些 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的引用了。 内存泄漏和内存使用这两个概念搞清楚?
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。