js不同数据类型的存储(内存中的堆和栈)

334 阅读3分钟

堆和栈的概念存在于数据结构中和操作系统内存中。但数据结构中的堆栈和内存中的堆栈是不同的!!!

数据结构中的堆与栈

数据结构(data structure)——数据的组织、管理和存储格式,使用目的是为了高效地访问和修改数据。

  • 线性结构(数组、链表,以及由它们衍生出来的、队列、哈希表等)
  • (二叉树,由它衍生出的二叉等)
  • 其它数据结构(跳表,哈希链表,位图等)

栈【先进后出First In Last Out(简称FILO)】

image.png

栈(stack)又名堆栈,是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除操作。这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。

两个最重要的操作是Push和Pop。 Push操作是在栈顶加入一个元素,使之成为新的栈顶元素,此操作称为进栈、入栈或压栈。Pop操作相反,把栈顶元素删除,使其相邻的元素成为新的栈顶元素,此操作称为出栈或退栈。

image.png

堆【优先队列,按优先级排序】

堆(heap), 一般也称作优先队列(Priority Queue)。二叉树是堆的一种实现方式,当且仅当满足所有节点的值总是不大于或不小于其父节点的值的完全二叉树被称之为堆。所以说堆是一种特殊的完全二叉树

在一个堆中,根节点是最大(或最小)节点。如果根节点最小,称之为小顶堆(或小根堆)。如果根节点最大,称之为大顶堆(或大根堆)。堆的左右孩子没有大小的顺序。

image.png

内存中的堆栈

在操作系统中,内存被分为栈区堆区

  • 栈区内存:由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

  • 堆区内存:一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。

js不同数据类型的存储

image.png

js 可以分为两种类型的值,一种是基础数据类型(又叫做简单类型值类型),一种是复杂数据类型(又叫做引用类型)。

两种类型的主要区别:存储位置不同

基础数据类型的值直接保存在栈中。这是因为这些基础类型的数据占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储,便于迅速查寻变量的值。

假设有如下 JS 代码:

var a = 1.23
var b = 3.14

对应的内存是这样:

复杂数据类型的值保存在堆中,通过使用在栈中保存对应的指针来获取堆中的值。 因为引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度,影响程序运行的性能。但地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

再加几行 JS 代码:

var obj = {}
var c = 1.628
obj.a = 1.23
obj.b = 2.34

对应的内存是这样的:

image.png

复杂数据类型在栈中存储的指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

值类型在赋值的时候拷贝值,引用类型在赋值的时候只拷贝地址,不拷贝值。

值类型的赋值举例:

var a = 1.23
var b = a

对应的内存结果为:

引用类型的赋值举例:

var a = {name: 'a'}
var b = a

对应内存结果为:

也就是说,a 和 b 都存储着「同一块内存」的地址!当我们修改 b.name 的时候,a.name 也会跟着改变。

[参考] zhuanlan.zhihu.com/p/22400319