原稿:语雀 · JS内存管理 · 原目录:JavaScript › JS内存管理
之前就想总结,拖拖拖,拖到今天写深拷贝时才整理
JS内存模型
JS引擎将内存空间分为两块:堆(heap)与栈(stack)
- JS中的原始数据类型值通常都存储在栈中(Number String Null Undefined Boolean Symbol)
- 而引用类型的数据都被存储在堆中(Object)
当使用原始数据值运算时,我们就是在操纵栈中的数据;但JS不允许直接访问堆空间,我们只能在栈中保存指向堆中数据的引用/指针/地址,在操作对象时,实际上是在操作对象的引用而不是实际的对象
例子:这段代码中不同变量实际的内存空间如下图所示
var a1 = 0; // 栈
var a2 = 'this is string'; // 栈
var a3 = null; // 栈
var b = { m: 20 }; // 变量b存在于栈中,{m: 20} 作为对象存在于堆内存中
var c = [1, 2, 3]; // 变量c存在于栈中,[1, 2, 3] 作为对象存在于堆内存中

函数执行中的内存管理
一个函数执行前后的内存管理的过程是什么样的?
\[强烈建议配合[JS运行机制](https://www.yuque.com/gesidalijiashidai/fgeemd/gi0181)中函数编译执行过程观看\]
|
C语言内存管理
为什么这里要提C语言,因为v8引擎基于C++,而引擎负责JS代码执行过程中的内存管理,换句话说JS的内存管理实际上就是C++内存管理的封装,了解C中的内存机制可以让你理解为什么会有heap与stack这样的数据结构
有兴趣和基础的同学可以去看我在系统级编程中做的关于内存布局和分配的笔记(Ch6 内存布局和分配)
语雀引用内容
stack与heap的出现主要是适应了不同的数据存储需求
- stack适合静态分配(也可动态):在处理程序源代码时分配内存空间,在程序执行之前进行,效率比较高,但因为需要提前分配,对于数据的大小需要预知,因此适合有明确类型的数据,如int、double、指针等
- heap只能动态分配:程序在执行过程中再进行内存分配,有更大的地址空间可分配,同时更灵活,但是分配效率会降低
以上的描述针对C程序,但是JS内存管理大致基于此封装,只不过静态动态分配的过程都被JS引擎负责了,归根结底,stack与heap的划分是为了适应不同的数据存取需求