JS中的堆和栈及内存泄漏
一、栈
从电脑内存中分配一块出来,用来执行代码的内存,Stack
先创建变量,再做赋值操作分配一个主线程来自上而下执行。(js单线程,浏览器多线程)主要用来运行代码,和存储基本类型。
1.基本数据类型储存
- 变量存储空间,存创建的变量
- 值存储空间,存基本数据类型的值
- 一个值存储空间可以对应多个变量,
一个变量只能对应一个值存储空间。
2.说明
栈内存:是一个执行代码的一个空间,这个调用栈只有一个,并且大小固定,按照一定的排列规则自上而下,顺序执行。通俗点说就是先进后出
3.堆栈溢出
溢出:因为栈内存空间有限,当你执行一些递归操作没有阻断或者释放的时候,反复调用,栈内存执行序列就会排不下了。
二、堆
- 从内存中有拿出来一块,用来存引用数据类型
Heap,一个16进制的地址。- 按照键、值分别存放,并关联起来
引用数据类型存储
堆内存不是有个地址么,放到栈内存的值存储空间,并和变量关联
三、深拷贝和浅拷贝
简单的说,浅拷贝就是只将对象 最外层 的键值复制为一个新的对象,而深拷贝则会 递归复制所有的层 ,直到该键的值为基本类型值。 再简单点说 ,经过浅拷贝后,新旧变量可能还会有所关联(既然说了是可能还有所关联,那也可能毫无关联吧,这里的关键就在于原对象的复杂程度了);而经过深拷贝后,理论上,新旧变量再无关联。 注意 ,在进行深拷贝时,层级不宜过多。所以,一般的深拷贝也并不是绝对毫无关联的。
var obj = {
a: "a is a",
arr: [ 1, 2, 3]
}, obj1 = { ...obj }, //假装这里是个浅拷贝
obj2 = JSON.parse(JSON.stringify(obj)); //假装这里是深拷贝。
obj1.a = "value a";
obj1.arr[0] = 66;
可以看到,当原对象的值为 基本类型值 时,浅拷贝和深拷贝并没有区别;而当原对象的某些值为 引用类型值 时,如果修改变量的值,浅拷贝会改变原对象的值,而深拷贝则不会。
四、垃圾回收
现在浏览器基本都在使用标记-清除的算法来执行垃圾回收。而不是使用引用计数的方式,因为引用计数方式无法释放循环引用结构的内存占用。 标记清除算法的核型概念是:从根部(在JS中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收。
五、内存泄露
对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。 对于不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)
常见的内存泄露
1. 不合理的计时器
2. 被共享的闭包作用域
3. 脱离dom引用
4. 意外的全局变量
此篇文章为转载,作为学习日志,出处不详,如有冒犯请原作者告知并删除