深入理解JavaScript内存管理和GC算法

深入理解JavaScript内存管理和GC算法

背景介绍

JavaScript是一门非常灵活多用途的语言,这得益于JavaScript内部的垃圾回收机制以及自动内存管理机制。不仅如此,了解这些机制将有助于我们编写出高效且易于维护的代码。

内存管理方法

JavaScript中,内存管理主要通过两种方法进行:栈(stack)和堆(heap)。

栈(Stack)

栈是一种有限制的数据结构,它存储了所有基本类型 (undefined,null,布尔类型,数字类型和字符串类型) 的变量,它们都是直接存在栈中的。当我们创建一个新的变量时,它就会被放到栈的顶部。当变量失去可访问性时,栈就会自动清除变量。

堆(Heap)

堆是开辟的一块内存区域,用于存储所有引用类型的变量。与栈不同的是,堆中的数据大小不固定,我们可以动态地创建对象。这意味着内存必须动态地分配,并在不再需要它们时释放。

垃圾回收机制

引用计数(reference counting)

垃圾回收的首要策略是引用计数(reference counting)。它是通过引用计数器实现的,每当有一个变量引用对象时,计数器就会加1,相反地,当对象不再被使用时,计数器就会减1。当计数器归零时,JavaScript会将对象从内存中移除。

但是,引用计数也存在一个大问题是循环引用。即使对象已经成为垃圾,仍有多个对象引用该变量,那么该对象就不能被回收。以下是一个例子:

let a = {}
let b = {}
a.foo = b
b.bar = a

以上代码中,ab 都指向对象 {},并且互相引用,就算再没有变量引用他们,他们仍然不会被垃圾回收,因为他们的引用计数不为0,这就是引用计数算法的局限性。

标记-清除(mark and sweep)

另一种垃圾回收技术是标记-清除(mark and sweep)。这种技术适用于解决引用计数算法的问题,在JavaScript中,标记-清除(makr and sweep) 算法正是所采取的垃圾回收策略。

标记-清除的流程如下:

  1. 从根节点开始(全局对象window)遍历所有的对象,标记所有能够从根节点到达的对象(可达对象)。
  2. 遍历所有的对象,清楚所有未标记的对象(不可到达的对象)。
  3. 对于所有被标记的对象进行垃圾回收,释放被占用的内存。

示例1

function foo() {
  let a = { 'name': 'John' }
  let b = { 'name': 'Jane' }

  a.friend = b
  b.friend = a
}
foo();

对上文的代码进行一下解析:

函数内创建了两个对象a、b。然后在a上定义了一个friend属性,并将它赋值为b。同样,b也有一个friend属性,指向a。这是一个循环引用。函数执行完毕后,这两个对象将会成为不可达的(没有变量引用它们),并且标记被删除。

总结

JavaScript提供了垃圾回收机制来确保内存占用的有效管理。我们可以看到,垃圾回收机制并不完美。对于循环引用,标记-清除算法可以解决这个问题。因此,当我们使用引用类型(对象、函数、数组等)时,一定要注意内存泄漏问题,以保证页面可以良好地运行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解JavaScript内存管理和GC算法 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 对python中Json与object转化的方法详解

    下面是“对Python中Json与Object转化的方法详解”的完整攻略。 1. Json与Object转化的背景 在Python中,常常需要处理Json数据以及Json字符串与Python对象之间的转化。在实际开发中,我们通常会使用如下的数据格式: { "name": "张三", "age": 1…

    C 2023年5月23日
    00
  • C++中如何将数据保存为CSV文件

    C++中可以使用标准库中的fstream类来将数据保存为CSV文件。下面是完整的攻略: 步骤一:打开文件 首先,可以使用fstream类中的open函数打开一个CSV文件,打开文件需要指定需要操作的文件名、打开方式和文件存取权限。如果文件不存在,则可以使用out模式或者app模式创建文件,如果文件已经存在,则可以使用in模式或者in+out模式打开文件。 #…

    C 2023年5月23日
    00
  • C语言中回调函数的使用详情

    回调函数是一种应用程序设计模式,通常在C语言中使用,用于将一个函数传递给另一个函数,以便后者在特定条件下调用前者。回调函数可以极大地提高程序的可扩展性和复用性。在这里,我们将详细讨论回调函数的使用方法,简单介绍一下回调函数的概念和用途,最后提供两个示例说明。 回调函数的概念和用途 回调函数是指在作为参数传递给另一个函数的函数。简单来说,回调函数是由另一个函数…

    C 2023年5月23日
    00
  • Android中gson、jsonobject解析JSON的方法详解

    Android中gson、jsonobject解析JSON的方法详解 什么是JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JSON的数据格式来描述数据对象。JSON是一种数据存储格式,它和XML的作用类似,但JSON是一种轻量级的、更易于读写的数据格式。JSON中的数据可以是数组或对象,通过层级的…

    C 2023年5月23日
    00
  • C语言中函数栈帧的创建和销毁的深层分析

    C语言中函数栈帧的创建和销毁的深层分析 什么是函数栈帧 在C语言中,每当一个函数被调用时,系统会在当前线程的栈上为该函数创建一个栈帧(Stack Frame),用于保存该函数调用时的现场信息(如首地址、传递参数、局部变量等信息)。函数栈帧的创建和销毁是函数调用的必要过程,也是C语言程序的基本运行机制之一。 函数栈帧的创建过程 函数栈帧的创建过程分为以下几个步…

    C 2023年5月23日
    00
  • android中一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值

    下面是详细的讲解: Unicode码值 Unicode是一个国际编码标准,用于为各种字符集中的每个字符分配唯一的数字标识符。Unicode用十六进制数表示每个字符,其中每个数字都有一个特定的名称和一个唯一的码位。而Android中的特殊字符的Unicode码值也是采用Unicode编码标准,可以在Unicode标准网站上查询。 特殊字符的Unicode码值示…

    C 2023年5月22日
    00
  • json 带斜杠时如何解析的实现

    在 JSON 中,斜杠 (/) 被视为特殊字符之一,用来转义其他字符,例如将双引号 (\”) 引用为字符串中的字符而不是字符串的结束标识符。JSON 规范定义,当转义序列被解码时,所有的反斜杠必须保留并被传播到最终结果中。 以下是处理 JSON 带斜杠的两条示例说明: 示例1:使用JSON.stringify()方法转换带斜杠的JSON 假设有一个 JSON…

    C 2023年5月23日
    00
  • IOS开发之路–C语言构造类型

    IOS开发之路–C语言构造类型 概述 在IOS开发中,C语言是必须要掌握的一门语言。而C语言中的构造类型在IOS开发中也有着广泛应用,例如结构体struct、枚举类型enum等等。本文将详细讲解C语言构造类型的使用步骤,以及在IOS开发中的应用。 结构体struct 结构体是一种将不同数据类型的数据按一定的顺序放在一起的自定义数据类型。在IOS开发中,结构…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部