堆栈内存释放

本文主要介绍了JS引擎中内存的分类,包括堆内存和栈内存,阐述了堆栈内存的创建和释放方式,以及栈内存不销毁的特殊情况。此外,还讲解了ES6新增的let和const关键字的特点,如无变量提升、重复声明报错等,以及const声明常量的细节问题。

js引擎中内存的分类
  1. 堆内存:堆内存是用来储存数据类型的
  2. 栈内存:栈内存提供js代码执行的环境,并储存引用数据类型的数据的
js中堆栈内存的创建和释放
  1. 创建堆内存

    • 创建一个引用数据类型的值(对象,数组,正则,时间,函数),这时浏览器会为这个引用数据类型创建一个堆内存,在这个堆内存中存储着这些引用数据类型的值.
  2. 堆内存的释放

    • 让所有引用堆内存空间地址的变量赋值为null即可(没有变量占用这个堆内存了,浏览器会在空闲的时候把它释放掉)
  3. 创建栈内存

    • 浏览器打开一个页面的时候,会首先形成一个顶层的栈内存,丫就是全局作用域window
    • 函数执行时产生的私有作用域就是一个供函数代码执行的栈内存
    • 函数每一次执行,都会形成一个全新的栈内存,即每次函数执行都是在一个全新的环境里面执行,所以函数每次执行都是互相独立的.
  4. 栈内存的销毁

    • 顶层栈(全局作用域)销毁,页面关闭,全局作用域销毁
    • 私有作用域销毁:一般情况下,函数执行后栈内存就销毁了,但是有些情况不会销毁
栈内存不销毁的特属情况

1.当函数执行完,如果返回了一个引用数据类型的值,且这个值被外面的属性或者变量接收,此时函数执行的作用域不会被销毁,储存在作用域中的值也不会销毁.
2.函数内部的引用数据类型被外部占用,函数执行的作用域不销毁。

let和const
  1. let和const的特点
    • let和const都是es6新增的关键字,let用来声明变量, const用来声明常量
    • let和const都不会进行变量提升,也就是说,如果在定义之前输出会报错
    • let和const重复声明会报错: Uncaught SyntaxError: Identifier ‘a’ has already been declared( 未捕获的语法错误:标识符’num’已被声明)
    • let和const在全局中声明不会给window增加属性
    • let和const会受到块级作用域的影响,且一定情况下会出现暂时性死区
  2. 暂时性死区(tdz)
    • 在代码块中,用let跟const声明的变量,不能在声明之前使用,这被称为暂时性死区
var num = 2;
{
num=3;
let num =3
}
  • 过去typeof被称为最安全的运算符,因为用它来检测一个尚未声明的变量也不会报错,但是在es6出来之后,因为暂时性死区的原因就不再适用了.
  1. const声明常量的细节问题
    • 1.声明常量时必须赋值,否则报错
      (Uncaught SyntaxError: Missing initializer in const declaration
      未能捕获的语法错误:用const声明时初始值缺失)
    • 2.常量一旦声明就无法改变,但如果声明的是一个引用数据类型,因为常量代表的是这个引用数据类型的空间地址,所以我们可以随意改变地址中的数据.但是不能修改常量存储的空间地址
### 堆栈内存的概念 堆栈内存(Stack Memory)是程序运行时用于管理函数调用和局部变量的一种内存区域。它遵循后进先出(LIFO, Last In First Out)的原则,即最后被压入堆栈的数据最先被弹出。堆栈内存由系统自动管理,通常用于存储函数调用时的参数、局部变量、返回地址等信息[^1]。 ### 堆栈内存的工作原理 堆栈内存通过一个称为**堆栈指针(Stack Pointer, SP)**的寄存器来跟踪当前堆栈的顶部位置。每当函数被调用时,系统会为该函数分配一块堆栈空间,称为**堆栈帧(Stack Frame)**或**活动记录(Activation Record)**。堆栈帧通常包含以下内容: 1. **函数参数**:调用函数时传递的参数。 2. **返回地址**:调用函数结束后程序应继续执行的地址。 3. **局部变量**:函数内部定义的变量。 4. **保存的寄存器状态**:在函数调用前后需要保存的寄存器值,以确保调用者的状态不会被破坏。 堆栈操作主要包括**压栈(Push)**和**弹栈(Pop)**两种操作: - **压栈**:将数据压入堆栈顶部,堆栈指针向下移动(在大多数系统中,堆栈向低地址方向增长)。 - **弹栈**:将数据从堆栈顶部弹出,堆栈指针向上移动。 例如,在函数调用过程中,调用者会将参数压入堆栈,然后跳转到被调用函数的入口地址。被调用函数会分配局部变量空间,并在执行结束后释放堆栈帧,恢复调用者的堆栈状态[^2]。 ### 堆栈内存在程序执行中的作用 堆栈内存的主要作用包括: 1. **函数调用支持**:堆栈内存为函数调用提供了必要的支持,确保函数能够正确地传递参数、保存返回地址并恢复调用环境。 2. **局部变量管理**:每个函数调用时分配的局部变量存储在堆栈中,函数返回后这些变量自动释放,避免内存泄漏。 3. **控制流管理**:堆栈通过保存返回地址,确保程序在函数调用结束后能够正确地返回到调用点继续执行。 4. **异常处理与调试**:堆栈帧的结构有助于调试器跟踪函数调用链,便于定位错误和分析程序状态。 ### 示例:函数调用中的堆栈操作 以下是一个简单的函数调用示例,展示了堆栈在函数调用中的作用: ```c int foo1(int m, int n) { int p = m * n; return p; } int foo(int a, int b) { int c = a + 1; int d = b + 1; int e = foo1(c, d); return e; } int main() { int result = foo(3, 4); return 0; } ``` 在执行`main`函数时,首先会将`foo`函数的参数`3`和`4`压入堆栈,然后跳转到`foo`函数的入口地址。`foo`函数会分配局部变量`c`、`d`和`e`的空间,并调用`foo1`函数。`foo1`函数同样会分配局部变量`p`的空间,并在返回时释放堆栈帧。最终,`foo`函数返回后,`main`函数的堆栈帧也会被释放[^2]。 ### 堆栈内存的适用场景 1. **高速缓存场景**:硬件堆栈常用于需要快速访问的场景,例如处理器的调用堆栈。 2. **大容量需求**:软件堆栈适用于需要较大内存空间的场景,通常通过动态分配实现。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值