JS中的栈和堆

基本概念

栈(stack):是栈内存的简称,栈是自动分配相对固定大小的内存空间,并由系统自动释放,数据结构遵循FILO(first in last out)先进后出的原则,较为经典的就是乒乓球盒结构,先放进去的乒乓球只能最后取出来;

 

堆(heap):是堆内存的简称,堆是动态分配内存,内存大小不固定,也不会自动释放,数据结构是一种无序的树状结构,同时它还满足key-value键值对的存储方式;我们只用知道key名,就能通过key查找到对应的value。比较经典的就是书架存书的例子,我们知道书名,就可以找到对应的书籍;

特点:

栈的特点开口向上、速度快,容量小;

堆的特点:速度稍慢、容量比较大;

栈和堆的联系

他们额联系就是 我们的 基础类型和引用类型的概念

基本数据类型Undefined,String,Boolean,Null,Number,都是直接按值存放在栈内存中,占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说,更加容易管理内存空间。同时也用来保存基本值和引用类型值的地址

引用数据类型:指那些可能由多个值构成的对象,如对象(Object)、数组(Array)、函数(Function) ,它们是通过拷贝和new出来的,这样的数据存储于堆中。

在这里就引出了引用类型深浅拷贝的问题,拷贝的是 引用类型的地址 还是 它的真实值。

内存分配垃圾回收

1.内存分配:

(1)栈内存:线性有序存储,容量小,系统分配效率高。

(2)堆内存:首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些了。  

2.垃圾回收

(1)栈内存:变量基本上用完就回收了,相比于堆来说存取速度会快,并且栈内存中的数据是可以共享的。

(2)堆内存:堆内存中的对象不会随方法的结束而销毁,就算方法结束了,这个对象也可能会被其他引用变量所引用(参数传递)。创建对象是为了反复利用(因为对象的创建成本通常较大),这个对象将被保存到运行时数据区(也就是堆内存)。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

局部变量和全局变量的销毁:

  • 局部变量: 局部变量的生存依赖于其函数执行上下文环境中,函数执行完毕后,其局部变量也很容易被垃圾收集器作出判断并回收。
  • 全局变量: 对于垃圾收集器而言,全局变量什么时候要回收是很难判断的。所以尽量少用全局变量,并且用完最好将其清空内存。

可能还是不太好理解,举个例子:

我们有一个函数 fn() 这个函数中有个变量 num,我们再函数外是没有办法拿到这个 num 的,就是因为他在函数结束就被销毁了

所有就有了 闭包(内存泄漏): 
1.保存函数(父函数)调用栈(栈内存)。

另外闭包为了解决什么问题而产生呢?
之所以额外维护一个栈内存,是因为栈内存的变量不会与其他栈内存的变量名冲突,我们也称之为作用域
普通函数寿命极短,因此作用域存活时间短;而闭包则是一个长期存活的函数作用域。
归根到底,
2.闭包是为了解决变量名冲突的问题。

另外插一嘴,为什么别人封装工具函数和模块,都使用闭包?
这和闭包的第一个作用有关。
如果不使用闭包,寿命极短,作用域创建即销毁,那么就是一个一次性工具。
使用闭包,它就能成为一个程序级别的工具,甚至是框架。

闭包参考文档:闭包 - JavaScript | MDN (mozilla.org)

内存参考文档:内存管理 - JavaScript | MDN (mozilla.org)

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
JavaScript是用来存储变量和数据的两种不同的内存区域。 是一种后进先出(LIFO)的数据结构,用于存储基本类型的变量和引用类型的指针。当我们声明一个变量时,它的值会被直接存储在内存。基本类型的值(如数字、布尔值、字符串等)被直接存储在,而引用类型的变量则存储了指向内存实际数据的指针。 是一种动态分配的内存区域,用于存储引用类型的数据。当我们创建一个引用类型的变量时,它的值实际上是一个指向内存对象的引用。对象本身的数据存储在内存,而的变量只是存储了指向内存对象的引用。 深拷贝是指创建一个新的对象,将原始对象的所有属性和嵌套对象的属性都复制到新对象。这样,新对象和原始对象是完全独立的,对新对象的修改不会影响原始对象。在JavaScript,可以使用不同的方法实现深拷贝,如使用JSON.parse(JSON.stringify(obj))或自定义递归函数来复制对象的属性和嵌套对象。 浅拷贝是指创建一个新的对象,将原始对象的属性复制到新对象,但嵌套对象的引用仍然指向原始对象的相同嵌套对象。这意味着对新对象的修改可能会影响原始对象。在JavaScript,可以使用Object.assign()或展开运算符(...)来实现浅拷贝。 总结来说,用于存储基本类型的变量和引用类型的指针,而用于存储引用类型的数据。深拷贝是创建一个新对象并复制所有属性和嵌套对象的值,而浅拷贝只复制属性,嵌套对象的引用仍然指向原始对象。 #### 引用[.reference_title] - *1* *3* [JavaScript 的区别](https://blog.csdn.net/qq_29850249/article/details/110500006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [JavaScript内存与内存分别是什么?](https://blog.csdn.net/qq_43807473/article/details/123816682)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值