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)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值