js中的栈和堆以及 js的内存模型

本文详细解释了JavaScript中的栈与堆概念,包括数据类型、栈的后进先出特性、堆的动态分配与引用类型存储。讨论了栈内存与堆内存的区别,以及内存分配、使用和回收的过程,特别强调了垃圾回收机制和V8引擎的内存管理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 栈和堆的概念

1.1  js的数据类型

值类型:数字number , 布尔 Boolean, 字符串string, 空null , 未定义的undefined

引用数据类型: 数组array  , 对象 object ,  函数function

区别:基本数据类型就是简单的数据段,引用数据类型是指由多个值构成的对象。

基本数据类型是按值访问,因为可以直接操作保存在变量中的实际值。存储在栈中。

引用类型是保存在堆内存中的对象,无法直接访问,只能通过操作对象在栈中的内存地址去调用。

1.2   栈

栈(stack):栈内存的简称,栈会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间。线性结构,后进先出,便于管理。

1.3  堆

堆(heap):动态分配的内存,大小不定也不会自动释放,存放引用类型,指那些可能由多个值构成的对象,保存在堆内存中,包含引用类型的变量,实际上保存的不是变量本身,而是指向该对象的指针。一个混沌,杂乱无章,方便存储和开辟内存空间。

引用类型是通过拷贝和new出来的,这样的数据存储于堆中。其实,说存储于堆中,也不太准确,因为,引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。

1.4  堆和栈的区别:

:所有在方法中定义的变量都是放在栈内存中,随着方法的执行结束,这个方法的内存栈也自然销毁。

优点:存取速度比堆快,仅次于直接位于CPU中的寄存器,数据可以共享;
缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

:堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(参数传递)。创建对象是2为了反复利用,这个对象将被保存到运行时数据区。

2. js内存模型

在栈内存中,我们可以细分为 地址和值,每当我声明一个变量就会为它创建一个地址以及值(包括null 等);我们调用的时候按址调用。堆内存在栈内存中也会创建一个栈的地址,然后他的值是在堆中的地址。

传值和传址:

var arr1 = [1,2,5,8];

var arr2 = arr1 ;

var str1 = arr1[2];

console.log(arr2);  //1,2,5,8

console.log(str1);  //5

arr2[4] = 99;

str1 = 6;

console.log(arr1);  //1,2,5,8,99

console.log(arr1[2]);  //5

因为arr1是数组,属于引用类型,所以它赋予给arr2的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象的值。str1得到的是一个基本类型的赋值,因此,str1仅仅是从arr1堆内存中获取了一个数值,并直接保存在栈中。arr1、arr2都指向同一块堆内存,arr2修改的堆内存的时候,也就会影响到arr1,str1是在栈中新创建了一个地址和值,并将str1指向新创建的地址,直接将当前的值赋给他,并不能影响到arr1堆内存中的数据。

JS环境中分配的内存一般有如下生命周期:

内存分配:当我们申明变量、函数、对象的时候,系统会自动为他 们分配内存

内存使用:即读写内存,也就是使用变量、函数等

内存回收:使用完毕,由垃圾回收机制自动回收不再使用的内存

JavaScript有自动垃圾收集机制,他的原理就是找出那些不再继续使用的值,然后释放其占用的内存。垃圾收集器会每隔固定的时间段就执行一次释放操作。
      在JavaScript中,最常用的是通过标记清除的算法来找到哪些对象是不再继续使用的,因此 a = null 其实仅仅只是做了一个释放引用的操作,让 a 原本对应的值失去引用,脱离执行环境,这个值会在下一次垃圾收集器执行操作时被找到并释放。而在适当的时候解除引用,是为页面获得更好性能的一个重要方式。

在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但是全局变量什么时候需要自动释放内存空间则很难判断,因此在我们的开发中,需要尽量避免使用全局变量,以确保性能问题。

以Google的V8引擎为例,在V8引擎中所有的JAVASCRIPT对象都是通过堆来进行内存分配的。当我们在代码中声明变量并赋值时,V8引擎就会在堆内存中分配一部分给这个变量。如果已申请的内存不足以存储这个变量时,V8引擎就会继续申请内存,直到堆的大小达到了V8引擎的内存上限为止(默认情况下,V8引擎的堆内存的大小上限在64位系统中为1464MB,在32位系统中则为732MB)。

另外,V8引擎对堆内存中的JAVASCRIPT对象进行分代管理。新生代:新生代即存活周期较短的JAVASCRIPT对象,如临时变量、字符串等;
老生代:老生代则为经过多次垃圾回收仍然存活,存活周期较长的对象,如主控制器、服务器对象等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值