堆栈
定义:
-
堆区与栈区都是程序运行时内存中分配的一个数据区,用于存放程序中的变量与数据;
-
二者存储的数据类型和处理速度不同;
-
栈(stack)中主要存放一些基本类型的变量和对象的引用,(包含池,池存放常量),其优势是存取速度比堆要快,并且栈内的数据可以共享,但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性;
-
堆(heap)用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象;它是运行时动态分配内存的,因此存取速度较慢。
基本数据类型:
Undefined、Null、Boolean、String、Number、Symbol都是直接按值直接存在栈中,每种类型的数据占用的内存空间大小都是固定的,并且由系统自动分配自动释放。
引用数据类型:
Object,Array,Function这样的数据存在堆内存中,但是数据指针是存放在栈内存中的,当我们访问引用数据时,先从栈内存中获取指针,通过指针在堆内存中找到数据。
let a = 123445;
let b = "asdasd";
let c = null;
let d = {age:20};
let e;
let f = true;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fh5QzJFk-1578915203151)(/static/upload/article/1578910200297.png)]
- 在定义的数据中,变量a,b,c,e,f,存储的是简单数据类型,所以直接存放。
- 变量d定义的是一个对象,对象属于复杂数据类型,会将其真实数据存放在堆区。
- 在堆内存中定义变量d,通过指针的方式引用所定义的对象,变量d中存储的是 对象在堆内存中的地址。
- const定义对象实,也是基于定义指向其在堆内存中的地址,所以const定义对象可以通过 点 操作改变对象中的值,而不能改变定义的简单数据类型的值。
不同:
- 申请方式不同。栈由系统自动分配,而堆是人为申请开辟;
- 申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
- 申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
- 底层不同。栈是连续的空间,而堆是不连续的空间。
案例
栈区
let a = 66;
let b = a;
console.log(++a,b+5);
//67 71
结论:堆区中存储的变量,相互赋值,应用不会应用原先的值,他们是相互隔离的
堆区
let person1 = {
name:"bob",
age:18,
sex:"boy"
};
let person2 = person1;
person2.name = "jack";
person2.age = "22";
console.log("person1:",person1);
console.log("person2:",person1);
console.log(person1 === person2);//判断两个对象是否全等
结果:
输出的结果中person1与person2的结果完全相同,全等判断也等于true,而我们操作只是操作了person2对象,理应不会修改person1中的值,但为什么出现了以上情形呢?
原因:
由于栈区,堆区存储数据类型不同,方式也不同,声明person1时的对象实际上是存储在了堆区,而变量person1则声明在栈区,通过指针的形式引用堆区中的对象,所以在为变量person2赋值时,复制的其实是对象的地址,也就是person1,person2所存储的都是堆区变量的同一地址,都是指向同一个对象,导致操作person1或person2实际都是操作的同一对象。
由于堆栈机制的存在,我们在对数据进行拷贝复制时,不能仅使用简单的赋值操作,这也是Js中为什么会存在深拷贝与浅拷贝的原因,下篇文章我们来盘深浅拷贝