在执行上下文一文中,我们简单的提到了栈这个概念,那么栈到底是一个什么东西呢,我们今天来详细的论述一下,在JavaScript中,栈和堆的这两个概念。
什么是栈,什么是堆
在JavaScript中,变量可以分为基本类型和引用类型两类,他们分别被保存在栈和堆中。
栈(stack):基本类型(String,Number,Boolean,Null,Undefined)会直接保存在栈中,栈会为他们自动分配固定的内存空间,也会自动释放。
堆(heap):引用类型(Function,Array,Object)并不会被分配固定的内存大小,而是通过动态分配内存的方式保存,大小不定,同时他也不会被自动释放。他们事实上是在栈内存中保存一个指针,并通过这个指针指向堆内存中的对象。
区别
栈是先进者后出,而堆属于队列优先,先进先出。
在栈内存的赋值时,我们称之为是传值,而堆内存的赋值我们称之为传址,因为多个变量可能指向同一个堆内存中的对象,所以某一个对象的改变,可能会引起其他变量的变化,而基本类型,则完全没有这方便的忧虑。
下面这段代码就给我们展示了这两种情况的区别:
let a = [1,2,3,4,5,6,7,8];
let b = a;
let c = a[0];
b[0] = 0;
console.log(a,b,c)

而也是堆的这种地址传递的特性,我们在对象的拷贝时,有了深拷贝和浅拷贝这两种区别。
const值的改变问题
const是es6中所新带来的变量声明,我们知道用const声明的变量是不能修改的,但是,他真的是完全不能修改的么?其实也不是,当他声明的是一个引用变量的时候,我们可以改变他的属性,像这样:
const a = {};
a.b = 'test';
这正是因为对象的赋值事实上是一个传址的操作,当我们给这个a变量添加属性b的时候,他的地址并没有发生改变,所以我们并没有改变这个变量a的值,所以它可以正常运行。