JavaScript 堆栈内存运行机制详解

作者:代码拾荒

时间:2026-10-25

浏览:102

本文深入解析 JavaScript 引擎中栈内存与堆内存的工作机制。栈内存用于存储基本类型变量及对象指针,负责代码执行环境;堆内存存储引用类型数据。文章详细阐述了执行上下文(EC)、变量对象(VO)的概念,以及浏览器如何通过引用计数法进行垃圾回收,帮助开发者理解内存分配、释放及性能差异。

文章目录

在 JavaScript 引擎中,变量存储主要涉及两个区域:堆内存(Heap)和栈内存(Stack)。栈内存通常用于存储基本类型变量,包括 Boolean、Number、String、Undefined 和 Null,同时也存储对象变量的指针(即地址值)。栈内存中的变量大小通常是已知或具有上限的,属于一种简单的存储方式。相比之下,堆内存主要负责存储如 Object 这类变量类型,其大小往往是不确定的。

栈内存 ECStack

栈内存 ECStack(Execution Context Stack,执行上下文栈)涉及作用域的概念。

JavaScript 之所以能在浏览器中运行,是因为浏览器为 JS 提供了基于栈内存的执行环境。

浏览器会在计算机内存中分配一块专用区域供代码执行,即栈内存 ECStack(Execution Context Stack,执行上下文栈)。每打开一个网页,都会生成一个全新的 ECS。

ECS 的作用

  • ECS 的主要作用是为 JavaScript 代码提供一个自上而下执行的环境,所有代码均在栈中执行。
  • 由于基本数据类型的值较为简单,它们直接在栈内存中开辟一个位置并将值存入其中。当栈内存被销毁时,存储在这些基本值也随之销毁。

堆内存

堆内存是存储引用值对应的空间,它是区别于栈区、全局数据区和代码区的另一个内存区域。堆允许程序在运行时动态申请特定大小的内存空间。

堆内存用于存储引用类型值,包括对象(键值对)和函数(代码字符串)。当内存被释放或销毁时,这些引用值将彻底消失,即触发堆内存释放。

当堆内存中没有被任何变量或其他对象占用时,浏览器会在空闲时段自主进行内存回收,销毁所有未被占用的内存。

在谷歌浏览器(基于 WebKit 内核)中,系统每隔一定时间会检查对象是否被占用。其采用的引用计数法机制是:当对象的引用计数为 0 时,释放该对象。

全局对象 GO(Global Object)在浏览器端由 WINDOW 指向 GO。

浏览器将一些内置的属性和方法收纳到单独的内存区域(堆内存)中。任何开辟的内存都拥有唯一的 16 进制内存地址,以便后期定位和访问该内存。

执行上下文 EC(Execution Context)是指代码执行所在的环境。

全局执行上下文 EC(G)中,函数内的代码会在一个单独的私有执行上下文中处理。块级执行上下文形成全局执行上下文后,会“进栈”进入栈内存执行;代码执行完毕后,形成的上下文可能会“出栈”并释放。

栈内存 ECStack

变量对象 VO(Varibate Object)是在当前上下文中用来存放创建的变量和值的地方。每个执行上下文都有自己独立的变量对象,在函数私有上下文中称为 AO(Activation Object,活动对象),但其本质仍是变量对象。

VO(G) 即全局变量对象,是全局上下文中存储全局变量的空间。它并非 GO,但在某些情况下,VO(G) 中的内容会与 GO 中的内容通过“映射机制”产生关联。

JS 中的内存主要分为堆内存和栈内存,两者的释放机制有所不同。

堆内存用于存储引用数据类型值(如对象键值对、函数代码字符串);栈内存则提供 JavaScript 代码执行的环境并存储基本类型值。

堆内存释放的方法是:将所有引用该堆内存空间地址的变量赋值为 null。此时没有变量占用该堆内存,浏览器会在空闲时将其释放。

栈内存释放的一般情况是:当函数执行完成,所形成的私有作用域(栈内存)会自动释放,其中存储的基本值也会随之释放。但也存在不销毁的特殊情况。

如果函数执行完成后,当前栈内存中的某些内容被栈内存以外的变量占用,此时栈内存不能释放,否则外部将无法找到原有的内容。

全局栈内存只有在页面关闭时才会被释放。

如果当前栈内存未被释放,那么之前存储在栈内存中的基本值也不会被释放,能够一直保存下来。

一般来说,栈内存采用线性有序存储,容量较小,系统分配效率较高。而堆内存首先需要在堆中分配新的存储区域,随后将指针(地址值)存储到栈内存中,因此效率相对较低。

在垃圾回收方面,栈内存变量基本上使用后即被回收;而堆内存中的变量由于存在许多不确定的引用,只有当所有指向堆内存的指针全部销毁后,才会被垃圾回收机制处理。

数据类型创建步骤

基本数据类型

var a = 12;

基本数据类型的创建步骤包括:创建一个值,创建一个变量,让变量与该值关联。基本数据类型值都是直接存储到栈内存中的。

引用数据类型

var a = {n:12};

引用数据类型的创建步骤包括:创建一个堆内存,将键值对存储到该内存中,并将堆内存地址放入栈中,供变量调用。

引用数据类型值都是先开辟一个堆内存,将数据存储进去,最后把地址放到栈中供变量关联使用。所有的指针赋值本质上都是指针的关联指向。

到此这篇关于 JS 堆栈内存的运行机制的文章就介绍到这了,更多相关 js 堆栈内存内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章