理解Javascript_01_理解内存分配原理分析
背景
Javascript 是一种动态、弱类型的编程语言,使用广泛,包括 Web 开发、桌面应用、移动应用等。Javascript 的运行需要内存支持,理解内存分配原理是深入学习 Javascript 的关键。
内存基础知识
在计算机中,内存被分为若干个存储单元,每个存储单元的大小是一个字节。我们可以通过内存地址来访问这些存储单元。在 Javascript 中,内存的使用分为栈和堆两种方式。
栈
栈是一种先进后出的数据结构,它由操作系统管理,存储函数调用时的上下文信息。在 Javascript 中,栈用来存储基本数据类型(如数字、字符串、布尔值等)以及引用类型的指针(如对象、数组、函数等)。
当我们创建一个基本数据类型(如 var a = 1;)时,会在栈中分配一块内存,存储这个变量的值。当我们创建一个引用类型(如 var obj = {};)时,会在栈中分配一块内存,存储这个变量指向的堆中的内存地址。这个对象实际的数据则存储在堆中。
堆
堆是一种动态分配内存的数据结构,它由程序员管理(通过 new、Object.create 等方法),存储对象和数组等引用类型的数据。
在 Javascript 中,堆中的数据是通过引用来访问的。例如,当我们访问一个变量的属性时,实际上是在堆中访问这个对象的属性。
Javascript 的内存管理
Javascript 使用垃圾回收机制来管理内存。垃圾回收机制会定期检查堆中的数据,将不再使用的数据标记为“垃圾”,然后释放内存。
标记清除算法
标记清除算法是垃圾回收的基本算法。算法工作原理如下:
- 首先,将所有堆中的数据标记为“未使用”。
- 然后,从根对象开始,遍历所有引用的对象,将其标记为“已使用”。
- 最后,扫描整个堆,将未标记数据释放。
这样就完成了一次垃圾回收。
引用计数算法
引用计数算法是最简单的垃圾回收算法。算法工作原理如下:
- 给所有对象添加一个计数器,初始化为 0。
- 当一个对象被引用时,增加计数器。
- 当一个对象不再被引用时,减少计数器。
- 当计数器为 0 时,释放对象占用的内存。
引用计数算法的缺点是无法处理循环引用的情况。例如,当两个对象相互引用时,它们的计数器永远不会变为 0,因此永远不会被释放。
示例说明
示例一:堆中的数据
var obj = {name: 'Tom', age: 18};
在这个示例中,我们创建了一个名为 obj 的对象,并在其中存储了 name 和 age 两个属性。这个对象的数据实际存储在堆中,obj 变量存储的是这个对象在堆中的内存地址。
示例二:标记清除算法
var a = {name: 'Tom'};
var b = {name: 'Jerry'};
a.friend = b;
b.friend = a;
在这个示例中,我们创建了两个对象 a 和 b,并将它们互相引用。这导致了循环引用的情况。对于标记清除算法来说,经过第一次遍历后,a 和 b 都被标记为“已使用”,因此它们都不会被释放。这样,这两个对象会一直占用内存,直到程序结束。这就是标记清除算法无法处理循环引用的一个例子。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:理解Javascript_01_理解内存分配原理分析 - Python技术站