什么是内存地址
JS内存地址是数据、对象、函数等在计算机中的储存位置,又分为堆(Heap) 与 栈(Stack),在开发工作中是无法直接读取内存地址的,而是通过变量其访问地址中的数据
内容分配
在 JavaScript 中创建个数据或函数时,JavaScript 引擎会为其开辟新的空间用来存数据,因此简称内存空间
变量类型
这里分为基本类型与引用类型,引用类型数组与对象在内容中的空间大小不固定,并且基本和引用的储存方式不同
通过上方介绍,相比对内存有了简单了解,以下是堆和栈的相关介绍
什么是堆和栈
1. 堆
描述:堆的主要作用是用来储存引用数据的值,如数组、对象,将值存在堆中,提供为栈(指向)访问
2. 栈
描述:栈可以对基本数据直接进行储存,包括函数的调用也在栈中,但是栈并不储存引用数据的值,只储存引用对象的指向,而调用此对象会通过指向在堆中读取
垃圾回收机制
1. 标记清除法
原理:标记清除算法针对全局对象进行定时标记,从根开始一步步往下进行查找并标记,如未别标记的数据过不了多久就会被当成垃圾并回收
蓝色区域为被标记且正常使用中,红色则相反会被回收。
2. 引用算法
原理:引用计算法每当数据被调用时进行计数 + 1,相反则 - 1,以此当计数为 0 时则意味着没有任何变量引用该数据,可以安全地释放该数据的内存空间。
问题:引用计算发无法处理循环引用,也就是循环对象相互引用会造成计数永不为 0 现象
let objA = {};
let objB = {};
objA.someProperty = objB;
objB.anotherProperty = objA;
以上代码对问题进行了解析,A对象引用B,相反B也一样,互相引用了对方,从而导致A引用B对象时,会 + 1,B也会如此,导致计数不会为 0。
相反如果只是 A 引用了 B 对象,B 会 + 1,当 A 不再引用 B 对象时则会 - 1。
目前市面上基本都为标记清除算法,相对优缺点上方已详细分析,在日常代码中随意定义不常用变量或是根本不用变量就会形成垃圾,当然 JavaScript 引擎会自动巡逻,清除一些不常用数据,但在此之前开发中也是可以避免,比如在循环中访问的变量、定时器任务、一些复杂的逻辑中要即时清除。