第170题:什么变量是存储在堆/栈?
堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(5)
什么变量保存在堆/栈中?
看到这个问题,第一反应表示很简单,基本类型保存在栈中,引用类型保存到堆中✌️ ✌️ ✌️ ,但仅仅就如此简单吗?我们接下来详细看一看
JS 数据类型
我们知道 JS 就是动态语言,因为在声明变量之前并不需要确认其数据类型,所以 JS 的变量是没有数据类型的,值才有数据类型,变量可以随时持有任何类型的数据 。
JS 值有 8 种数据类型:
true
和false
undefined
null
253 - 1
的整数其中前 7 种数据类型称为基本类型,把最后一个对象类型称为引用类型
JS中的变量存储机制
JS 内存空间分为栈(stack)空间、堆(heap)空间、代码空间。其中代码空间用于存放可执行代码。
栈空间
栈是内存中一块用于存储局部变量和函数参数的线性结构,遵循着先进后出 (LIFO / Last In First Out) 的原则。栈由内存中占据一片连续的存储空间,出栈与入栈仅仅是指针在内存中的上下移动而已。
JS 的栈空间就是我们所说的调用栈,是用来存储执行上下文的,包含变量空间与词法环境,var、function保存在变量环境,let、const 声明的变量保存在词法环境中。
这段代码很简单,就是创建了一个
add
函数,然后调用了它。下面我们就一步步的介绍整个函数调用执行的过程。
在执行这段代码之前,JavaScript 引擎会先创建一个全局执行上下文,包含所有已声明的函数与变量:
从图中可以看出,代码中的全局变量
a
及函数add
保存在变量环境中。执行上下文准备好后,开始执行全局代码,首先执行
a = 1
的赋值操作,赋值完成后 a 的值由 undefined 变为 1,然后执行
add
函数,JavaScript 判断出这是一个函数调用,然后执行以下操作:至此,整个函数调用执行结束了。
上面需要注意的是:函数(add)中存放在栈区的数据,在函数调用结束后,就已经自动的出栈,换句话说:栈中的变量在函数调用结束后,就会自动回收。
所以,通常栈空间都不会设置太大,而基本类型在内存中占有固定大小的空间,所以它们的值保存在栈空间,我们通过 按值访问 。它们也不需要手动管理,函数调时创建,调用结束则消失。
堆
堆数据结构是一种树状结构。它的存取数据的方式与书架和书非常相似。我们只需要知道书的名字就可以直接取出书了,并不需要把上面的书取出来。
在栈中存储不了的数据比如对象就会被存储在堆中,在栈中只是保留了对象在堆中的地址,也就是对象的引用 ,对于这种,我们把它叫做 按引用访问 。
举个例子帮助理解一下:
所以,堆空间通常很大,能存放很多大的数据,不过缺点是分配内存和回收内存都会占用一定的时间
JS中的变量存储机制与闭包
对以上总结一下,JS 内存空间分为栈(stack)空间、堆(heap)空间、代码空间。其中代码空间用于存放可执行代码
闭包
那么闭包喃?既然基本类型变量存储在栈中,栈中数据在函数执行完成后就会被自动销毁,那执行函数之后为什么闭包还能引用到函数内的变量?
在执行完函数
foo
后,foo
中的变量num
应该被弹出销毁,为什么还能继续使用喃?这说明闭包中的变量没有保存在栈中,而是保存到了堆中:
所以 JS 引擎判断当前是一个闭包时,就会在堆空间创建换一个“closure(foo)”的对象(这是一个内部对象,JS 是无法访问的),用来保存 num 变量
注意,即使不返回函数(闭包没有被返回):
总结
JS 就是动态语言,因为在声明变量之前并不需要确认其数据类型,所以 JS 的变量是没有数据类型的,值才有数据类型,变量可以随时持有任何类型的数据。
JS 值有 8 种数据类型,它们可以分为两大类——基本类型和引用类型。其中,基本类型的数据是存放在栈中,引用类型的数据是存放在堆中的。堆中的数据是通过引用和变量关联起来的。
闭包除外,JS 闭包中的变量值并不保存中栈内存中,而是保存在堆内存中。
原文
一般来说栈中存储的是基本类型的值和对象的引用,堆中存储的是对象,但这些都不是绝对的
基本类型值在内存中占据固定大小,被保存在栈内存中,引用类型值是对象,保存在堆内存中。栈是有结构的,先进后出,存放基本类型和对象的引用,每个区块的大小是明确的。heap没有结构,数据任意存放。
你说反了吧
貌似: 原始数据类型存在堆 , 引用数据类型存在栈