当前位置: 首页 > news >正文

计算机内存中的栈和堆

一、堆栈的定义

程序运行时,内存会划分出不同区域,其中最重要的两块就是栈(Stack)堆(Heap)

1. 栈(Stack)

  • 结构:一种线性的、后进先出(LIFO)的数据结构。
  • 管理方式:由操作系统或 JavaScript 引擎自动分配和释放,无需开发者手动干预。比如函数调用时,局部变量入栈;函数执行完,整块栈帧直接弹出,内存瞬间回收。
  • 特点
    • 速度快,直接通过移动栈指针来分配。
    • 空间相对较小,连续存储。
    • 存储大小固定、生命周期可预知的数据。

2. 堆(Heap)

  • 结构:更像一个杂乱但自由的大仓库,存储区域不一定连续,通过指针引用。
  • 管理方式动态分配。何时分配、何时释放并不严格跟随函数进出,而是由垃圾回收器(GC)通过算法判断对象是否还被使用,来决定回收时机。
  • 特点
    • 速度较慢,涉及内存查找与 GC。
    • 空间大,适合存放大小不定或需要长期存在的数据。

打个比方:栈像便捷的随身口袋,放快取快,但容量小;堆像家里的储物间,空间大但找东西(及收拾)要花时间。


二、JavaScript 的数据类型

JavaScript 的值分为两大阵营:

原始类型(Primitive)

  • undefined
  • null
  • boolean
  • number
  • bigint
  • string
  • symbol

它们的特点:不可变,大小相对固定(除了某些长字符串,但引擎有优化)。

对象类型(Reference / Object)

  • ObjectArrayFunctionDateRegExpMapSet等。
  • 特点:可变,结构复杂,大小动态增减

三、存储地方:栈与堆的“分工”

1. 基本数据类型的存储

绝大多数情况下,原始类型的值直接存在栈中。

  • 变量声明时,引擎会在栈中划分一块区域,把值直接放进去(比如数字10,布尔true)。
  • 栈变量本身持有这个原始值,不经过任何中间地址。

⚠️ 有一些“特殊”的原始值,如较长的字符串,引擎内部可能会把它们放进堆,而在栈上只存一个引用。这属于引擎优化,但从逻辑语义上,我们仍把字符串当作原始类型,赋值时依然会复制,行为上等同于直接存值

2. 对象数据类型的存储

对象的数据实体始终存放在堆内存中,而栈中只存储一个“门牌号”——即堆内存的引用地址。

  • 当你写let obj = { name: 'Alice' };,引擎会做两件事:
    1. 在堆中分配一块内存存放对象{ name: 'Alice' },得到一个地址(比如0x003FFF)。
    2. 在栈中给变量obj分配空间,里面存的值正是这个地址0x003FFF

访问obj.name时,先通过栈里的地址找到堆中的对象,再取出其属性。

这种分工的原因在于:对象大小可能在运行时随时变化(增减属性),把这种不稳定的数据放在容量有限、空间连续的栈里很危险。而栈只需保存一个固定大小的内存地址即可。


四、存储方式:按值 vs 按引用

这是区分原始类型和对象类型最核心的行为差异。

1. 原始类型 —— 按值存储和复制

操作直接对“值”本身进行,互不影响。

leta=10;letb=a;// 把 a 的值 10 复制一份给 bb=20;console.log(a);// 10,a 不变

a 和 b 在栈中有各自独立的空间,改一个不会影响另一个。

2. 对象类型 —— 按引用存储和复制

变量保存的是“引用地址”,复制时只复制地址,而不在堆里复制整个对象。

letobj1={name:'Alice'};letobj2=obj1;// 复制的是地址,obj2 也指向堆里同一个对象obj2.name='Bob';console.log(obj1.name);// 'Bob',obj1 跟着变了

obj1 和 obj2 里的地址相同,因此通过任何一个变量修改对象,都会反映在另一个上。

函数的参数传递也遵守同样规则:

  • 传原始类型:函数内部修改形参不会影响外部实参。
  • 传对象:修改对象属性会影响外部,因为内外指向同一个对象。
functionchange(num,obj){num=100;// 改的是局部副本obj.name='Zoe';// 改的是堆里的同一对象}letn=1;leto={name:'Tom'};change(n,o);console.log(n);// 1,未变console.log(o.name);// 'Zoe',变了

五、为什么要这样设计——深度理解

  1. 性能与效率
    栈分配只需移动指针,极快。原始类型大小已知、占用固定,适合栈。对象如果直接放在栈中,其动态扩展会引起大量内存搬移;放在堆中,栈上只保留一个指针,保持高效。

  2. 生命周期管理
    局部变量一般随函数退出销毁,栈自动弹出。对象却可能被多个变量引用、逃逸出当前作用域,堆配合垃圾回收能处理复杂存活分析。

  3. 内存布局与安全性
    栈连续、有序,容易产生栈溢出;堆则分散。把不确定性大的对象放堆,也让栈维持轻量安全。


六、进阶:那些“纯粹”之外的存储情况

实际引擎(如 V8)会优化存储,比如:

  • 小整数(Smi):可能直接编码在指针里,避免额外分配。
  • 字符串:字符串常量池,可能会在堆中存储,但逻辑上仍是不可变的原始类型。复制字符串时,通常表现为复制引用(写时复制),但对开发者透明,行为仍符合“按值传递”。
  • 闭包引用的变量:如果函数引用了外部原始类型变量,这个变量会被移到堆中(放在“环境”对象里),从而延长生命周期。这时原始值确实存在了堆里,但从语言视角它还是“原始值”,只是存在位置变成了堆。

这些实现细节不影响我们理解的大原则:原始类型表现为“值语义”,对象类型表现为“引用语义”;栈负责快速管理大小固定的值或地址,堆负责承载复杂动态的数据实体。


七、总结

  • 堆栈定义:栈是自动分配释放、有序快速的小容量区域;堆是动态分配、靠 GC 回收的大容量区域。
  • 存储地方:基本数据类型直接存于栈(值本身);对象实体存于堆,栈里只留堆地址。
  • 存储方式:基本类型按值复制,对象类型按引用复制。
  • 设计意图:兼顾性能与灵活性,让小而短命的数据速生速灭,大而长命的数据由堆和垃圾回收精细管理。

理解这一模型后,JavaScript 里赋值、传参、比较(===对对象比较地址)等常见行为就都有了坚实的底层基础。

http://www.rkmt.cn/news/1484826.html

相关文章:

  • 【钢铁雄心4】超简单低延迟保姆级联机教程,一分钟学会钢铁雄心局域网联机!!
  • Scikit-image图像处理实战:从蒙娜丽莎解构到医学级滤波
  • 手把手教你用HTML+CSS复刻一个简约风个人主页(附完整源码和素材)
  • VS Code + AWS SSM零配置远程开发实战
  • VSCode + Ollama + Continue 本地 AI 代码助手 实操手册
  • 别再混淆了!用PyTorch的ConvTranspose2d手把手搞懂反卷积(附代码验证)
  • 国内优质的静音发电机企业口碑推荐,附近发电机/高压发电机租赁/应急发电机/本地发电机出租,静音发电机品牌哪家强 - 品牌推荐师
  • Matlab大气湍流相位屏生成工具:Zernike建模+波前仿真+斯特雷尔比评估
  • 大模型工程化跃迁:OpenAI 4.1、grok-3与Scaling Laws实战指南
  • 第3章 Agent 类型分类与设计模式
  • 2026年6月郑州黄金回收店推荐:五大专业评测报价透明防压价案例 - 品牌推荐
  • 2026年最新邢台市黄金回收店铺TOP5排行榜 黄金+白银+铂金+K金回收门店指南及联系方式电话推荐 - 大熊猫898989
  • Wine Quality 可复现机器学习实验:随机森林二分类实战
  • 2026年众智商学院软考中级系统集成资料领取和题库怎么核对?官网400冯老师费用咨询 - 众智商学院职业教育
  • 别再傻傻分不清了!电磁继电器和磁保持继电器到底怎么选?看完这篇就懂了
  • 大模型工具描述优化:提升Agent调用准确率的核心基建
  • 2026年最新清远市黄金回收店铺TOP5排行榜 黄金+白银+铂金+K金回收门店指南及联系方式电话推荐 - 大熊猫898989
  • 2026 浙江衢州彩钢瓦修缮 TOP4 权威推荐|厂房金属屋面翻新防水补漏 + 避坑指南 - 本地便民网
  • 别再手动改报表了!用FineReport V9.0的复选框控件,5步搞定动态列展示(附完整SQL与公式)
  • OpenSpeedy完整指南:免费开源游戏加速工具的终极使用教程
  • uniapp多端朋友圈+ThinkPHP后端完整可运行项目,含数据库与一键部署指南
  • 避坑指南:ArcGIS里做IDW插值,你的搜索半径和幂值设置对了吗?
  • 长护险机构台账管理优化:轻量化提醒工具落地实践
  • Linux基础知识(一)
  • 2、K8S网络概述
  • LangChain Middleware:Agent 里的 AOP 治理层
  • 从零到一:Swin Transformer图像分类实战(PyTorch版)
  • Flutter 字体配置实战
  • 通用视觉软件-通信功能
  • 从‘虚短虚断’到电路设计:手把手教你用运放搭建一个简易音频混合器(加法器)和平衡输入电路(减法器)