js的内存泄露与垃圾回收机制

前言:

        首先读之前我们要了解几个基本概念

        基本类型:Undefined/Null/Boolean/Number/String        放在栈内存

        引用类型:object        放在堆内存

         js不允许直接访问内存中的位置,也就是不能直接访问操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。

        堆内存:程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则导致内存泄露。(内存泄露:下文会解释)   


1.什么是动态分配内存?

        动态内存分配就是内存不是在程序启动时分配,而是在运行中分配

2.为什么要动态分配内存?

        1.有些程序启动时并不清楚需要分配多少内存,得等到运行时才能清楚要分配多少。

        2.为了更高效的利用内存。某些内存只在运行中的某个时段需要使用,运行中的其他时段可以另作他用。

3.什么是内存泄露?

        不再用到的内存,没有及时释放,就叫做内存泄漏。(越攒越多最后就炸了)

4. js内存泄露存在吗?

        误区一:提供内存垃圾回收机制的编程语言如JavaVB.NET,能完全避免内存泄漏。

        这类编程语言需要将引用设为null,然后内存才会自动释放。

        所以,虽然JS支持垃圾回收机制,但是JS也会发生内存泄露

5.什么是垃圾?

        通俗来说,没有被引用的对象就是垃圾(还有一种情况:几个对象相互引用形成了一个环,相互引用,但是访问不到他们)(本地函数的局部变量和参数,当前嵌套调用链上的其他函数的变量和参数,全局变量等。这些无法删除统称为)

6.什么是垃圾回收机制?(GC)

        有些语言(比如 C 语言)必须手动释放内存,程序员负责内存管理。这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这被称为"垃圾回收机制"(garbage collector)。

7.垃圾回收机制的必要性?

        下面这段话引自《JavaScript权威指南(第四版)》

        由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。

8.js垃圾回收机制的常见两种方法:

    引用计数法:(IE等老牌浏览器)

        语言引擎有一张"引用表",保存了内存里面所有的资源(通常是各种值)的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。

左下角的两个值,没有任何引用,所以可以释放  

        上面代码中,数组[1, 2, 3, 4]是一个值,会占用内存。变量arr是仅有的对这个值的引用,因此引用次数为1。尽管后面的代码没有用到arr,它还是会持续占用内存。

如果增加一行代码,解除arr对[1, 2, 3, 4]引用,这块内存就可以被垃圾回收机制释放了。

    标记-清除算法(谷歌等现代浏览器)

        1.垃圾回收机制从开始一步步向下标记它们的引用

        2. 删掉那些没被标记的对象

9.常见的js内存泄露方式

    1.意外的全局变量

        未定义的变量会在全局对象创建一个新变量。(在浏览器中,全局对象是 window)

        另一种意外的全局变量可能由this创建:

    2.DOM泄漏

        下面有个很简单的一个例子,当我点击remove按钮删除test的时候,就会造成内存泄露。为什么呢?

        原因就是删除的DOM在js中有全局的引用。也就是我删除的test在文中被引用,所以无法释放内存。所以在删除更新等操作后应该将其设置为null。

    3.闭包

        在my()内部创建的sendName()函数是不会被回收的,因为它被全局变量test引用,处于随时被调用的状态。如果向释放内存可以设置test=null;由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多。

    4.被遗忘的计时器或回调函数

        定时器要清除,内存才会被回收。回调函数也要赋null

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容