1. JS 数据类型
首先我们来认识js的七种数据类型:
1.基本数据类型
String
Number
Boolean
null
undefined
Symbol
BigInt
2.引用数据类型
Object
2. 什么是栈与堆
一般来说JS的内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。
其中栈存放变量,堆存放复杂对象,池存放常量,所以也叫常量池。
通俗点说就是:栈是存放基本数据类型及对象变量的指针的,堆是存放引用数据类型的
堆内存与栈内存是有区别的:
栈内存运行效率比堆内存高,空间相对推内存来说较小,反之则是堆内存的特点。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。
3. 变量类型与内存的关系
1.基本数据类型与栈的关系
基本数据类型保存在栈内存中,因为基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。
PS: 需要注意的是闭包中的基本数据类型变量不保存在栈内存中,而是保存在堆内存中。
举例说明:
let a = 20
let b = a
b = 30
console.log(a,b) // a = 20 b = 30
在变量对象中执行数据复制的时候,其实系统会自动为新的变量分配一个新的值,所以a与b其实已经是完全独立的两个变量,只是值一样而已。
1.引用数据类型与堆的关系
1.引用类型:Array,Function,Object...除了上文提到的基本数据类型以外,所有类型都是引用数据类型。
引用数据类型存储在堆内存中,因为引用数据类型占据空间大、大小不固定。 如果存储在栈中,将会影响程序运行的性能;
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。 当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
举例:
var m = {
a:10,
b:20
};
var n = m;
n.a = 15;
console.log(m.a); //15
因此当我们要访问堆内存中的引用数据类型时,实际上我们首先是从变量中获取了该对象的地址指针, 然后再从堆内存中取得我们需要的数据。
4.栈内存和堆内存的垃圾回收
栈内存中变量一般在它的当前执行环境结束就会被销毁被垃圾回收制回收, 而堆内存中的变量则不会,因为不确定其他的地方是不是还有一些对它的引用。 堆内存中的变量只有在所有对它的引用都结束的时候才会被回收。
5.闭包与堆内存
闭包中的变量并不保存中栈内存中,而是保存在堆内存中。 这也就解释了函数调用之后之后为什么闭包还能引用到函数内的变量。
我们先来看什么是闭包:
function A() {
let a = 1;
function B() {
console.log(a);
}
return B;
}
let res = A();
函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。
函数 A 弹出调用栈后,函数 A 中的变量这时候是存储在堆上的,所以函数B依旧能引用到函数A中的变量。
现在的 JS 引擎可以通过逃逸分析辨别出哪些变量需要存储在堆上,哪些需要存储在栈上。