首页 > 专栏 > 前端 > 文章详情
内存中的堆和栈怎么理解,如何对 JavaScript 算法产生的影响(二) 发布于:2021-03-03 14:36:16   原创发表   查看:4  讨论:0
数据结构的栈和堆qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
首先在数据结构上要知道堆栈,尽管我们这么称呼它,但实际上堆栈是两种数据结构:堆和栈。堆和栈都是一种数据项按序排列的数据结构。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
栈方法(数据结构):qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
JavaScript的数组模拟栈行为,使用的是一种可以限制你插入和删除项的数据结构。qLe易塔云建站-模板下载,web开发资源,技术博客
栈就是其一,顾名思义,栈道,栅栏,就是一个一个安装,后面安装的先拆除(如果需要拆除)修理。qLe易塔云建站-模板下载,web开发资源,技术博客
而栈中项的插入(推入)和移除(弹出),只发生在一个位置---栈的顶部。使用JavaScript的push()和pop()方法,以便实现类似栈的行为。
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
堆方法(数据结构):qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
    □:而堆就不同了,堆是一种经过排序的树形数据结构,每个结点都有一个值。qLe易塔云建站-模板下载,web开发资源,技术博客
    □:通常我们所说的堆的数据结构,是指二叉堆。qLe易塔云建站-模板下载,web开发资源,技术博客
    □:堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
由于堆的这个特性,常用来实现优先队列,堆的存取是随意,这就如同我们在图书馆的书架上取书,qLe易塔云建站-模板下载,web开发资源,技术博客
虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
内存中分配堆和栈qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
堆栈的空间分配:qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
    □:栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。qLe易塔云建站-模板下载,web开发资源,技术博客
    □:堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
堆栈的缓存方式:qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
    □:栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。qLe易塔云建站-模板下载,web开发资源,技术博客
    □:堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
js中的堆内存和栈内存:qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
    □:JavaScript中栈内存用来存储各种基本类型的变量,包括Boolean、Number、String、Undefined、Null...以及对象变量的指针,这时候栈内存给人的感觉就像一个线性排列的空间,每个小单元大小基本相等,栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储。qLe易塔云建站-模板下载,web开发资源,技术博客
    □:JavaScript中堆内存主要负责像对象Object这种变量类型的存储,堆内存存储的对象类型数据对于大小这方面,一般都是未知的,(所以这大概也是为什么null作为一个object类型的变量却存储在栈内存中的原因)。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
感受一下JavaScript中的堆和栈qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
测试基本数据类型:
var a = 1;qLe易塔云建站-模板下载,web开发资源,技术博客
var b = 1;qLe易塔云建站-模板下载,web开发资源,技术博客
console.log(a === b);//trueqLe易塔云建站-模板下载,web开发资源,技术博客
var c = "水电费";qLe易塔云建站-模板下载,web开发资源,技术博客
var d = "水电费";qLe易塔云建站-模板下载,web开发资源,技术博客
console.log(c === d);//true
基本数据类型,因为都是存在栈内存中的,以上面的int为例:qLe易塔云建站-模板下载,web开发资源,技术博客
var a = 1;变量 a 存在栈内存中,他的值是基本数据类型(int),自然也是在栈内存中,栈内存有没有1?没有那就拿出一块内存存1,这个变量a指向这块值为1的栈内存地址;qLe易塔云建站-模板下载,web开发资源,技术博客
var b = 1;同理,变量 b 也是在栈内存中的,但是赋值的时候,发现,栈内存有一块地址存着int型的值1,那么就直接指向这块栈内存了;qLe易塔云建站-模板下载,web开发资源,技术博客
所以最终 a === b 是 true;qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
测试引用数据类型:qLe易塔云建站-模板下载,web开发资源,技术博客
 
var a = new Number(10);qLe易塔云建站-模板下载,web开发资源,技术博客
var b = new Number(10);qLe易塔云建站-模板下载,web开发资源,技术博客
console.log(a === b);//false
qLe易塔云建站-模板下载,web开发资源,技术博客
new关键字生成的对象都是存在于堆内存中的,上述代码中:qLe易塔云建站-模板下载,web开发资源,技术博客
var a = new Number(10);变量 a 存在于栈内存中,他的值是一个指针,这个指针指向堆内存中的一个对象!b的值也是一个指针,指向的是堆内存中的这个对象。qLe易塔云建站-模板下载,web开发资源,技术博客
所以两个指针不相等。a和b在栈内存中也开辟了空间,各自不相关。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
C语言解释:
int a = 20;//实际变量的生命qLe易塔云建站-模板下载,web开发资源,技术博客
int * ip;//指针变量的声明qLe易塔云建站-模板下载,web开发资源,技术博客
ip = &a;//在指针变量中存储着 变量a 的地址
所以我们应该这么理解:qLe易塔云建站-模板下载,web开发资源,技术博客
    □:普通变量的值类型是基本数据类型,指向栈内存中的一块地址;qLe易塔云建站-模板下载,web开发资源,技术博客
    □:引用类型变量的值是指针,指向堆内存中的一块地址。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
指针的赋值:
/* 指针赋值 */qLe易塔云建站-模板下载,web开发资源,技术博客
var a = new String('桔子桑');qLe易塔云建站-模板下载,web开发资源,技术博客
var b = a;qLe易塔云建站-模板下载,web开发资源,技术博客
console.log(a === b);//true
我们看到,指针型变量 a 的值是一个指针,指向堆内存中一块地址;然后 又定义了一个变量 b ,他的值等于 a,a 的值是什么?a 的值是一个指针啊,那么变量 b 就等于这个指针,自然也是指向堆内存的那一块地址咯。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
const关键字:qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
我们知道const关键字用来定义一个常量,const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个栈内存地址,因此等同于常量。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
但对于复合类型的数据(主要是对象和数组),变量指向的栈内存地址,保存的只是一个栈内存指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
所以,const保证的是栈内存这边变量与其值不能发生改变,所以对于复合类型,指针指向的堆内存中存的数据结构能否改变是左右不了的。
/*const关键字*/qLe易塔云建站-模板下载,web开发资源,技术博客
const a = 1;qLe易塔云建站-模板下载,web开发资源,技术博客
a = 2;qLe易塔云建站-模板下载,web开发资源,技术博客
console.log(a);qLe易塔云建站-模板下载,web开发资源,技术博客
const b = {qLe易塔云建站-模板下载,web开发资源,技术博客
    name : "Jerry"qLe易塔云建站-模板下载,web开发资源,技术博客
}qLe易塔云建站-模板下载,web开发资源,技术博客
b.name = "Tom";
对于前者,因为常量 a 和他的值都是在栈内存中的,不能更改,手动修改只会报错:qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
qLe易塔云建站-模板下载,web开发资源,技术博客
而对于后者,因为常量 b 的值是一个指针,这个指针由于存在于栈内存,所以他的指向是不能更改的(堆内存地址),但是对应堆内存地址中存的数据结构(存了一个对象)是可以更改的。

评论

  • 匿名