Skip to content

JavaScript变量在内存中的堆栈存储 ​

栈 ​

主要用于

  • 存放 基本类型变量
  • 存放函数调用信息
  • 记录执行上下文

特点:

  • 存取速度快

  • 占用空间小

  • 自动分配释放

  • 基础类型会存放与栈,引用类型会存放在堆

  • 案例:以下代码为什么输出50 30

javascript
function fn(obj) {
  obj = { m: 50 }
  console.log(obj.m)
}
const o = { m: 30 }
fn(o)
console.log(o.m)

解析 ​

这段代码的关键在于理解函数参数的按值传递(Call by Value)以及引用类型的存储方式。

1. 初始状态 ​

javascript
const o = { m: 30 }
  • 堆内存(Heap):创建了一个对象 { m: 30 },假设它的内存地址是 0x001。
  • 栈内存(Stack):变量 o 存储了该对象的引用(即地址 0x001)。

2. 调用函数 fn(o) ​

javascript
fn(o)
  • 函数 fn 被调用,创建了一个新的执行上下文。
  • 参数传递:JS 中函数参数是按值传递的。
    • 这里传递的是变量 o 的值,也就是地址 0x001。
    • 所以,函数内部的局部变量 obj 初始时也指向地址 0x001。
    • 此时:o -> 0x001, obj -> 0x001。

3. 函数内部执行 ​

javascript
obj = { m: 50 }
  • 堆内存:创建了一个新对象 { m: 50 },假设它的地址是 0x002。
  • 赋值操作:将这个新地址 0x002 赋值给局部变量 obj。
  • 关键点:这个赋值操作切断了 obj 与原对象 0x001 的联系。
    • 此时:obj -> 0x002。
    • 外部变量 o 仍然指向 0x001,完全没有受到影响。
javascript
console.log(obj.m)
  • 输出 obj 指向的新对象(0x002)的 m 属性,即 50。

4. 函数执行结束 ​

  • 函数上下文销毁,局部变量 obj 释放。
  • 外部代码继续执行。
javascript
console.log(o.m)
  • 访问外部变量 o。
  • o 始终指向原对象(0x001),其内容 { m: 30 } 从未被修改。
  • 输出 30。

总结图示 ​

stack-heap