JavaScript的内存管理

JavaScript的内存管理

PluginsKers
2021-03-06 / 0 评论 / 234 阅读 / 正在检测是否收录...

内存的生命周期

在javascript中,当我们创建变量、函数或者其它的时候,JS引擎会为它分配内存并在不需要的时候释放内存

分配内存是在内存中保留空间的过程,释放内存则是释放空间以便于其它目的

每一次创建变量或者声明函数的时候,内存总要经历以下过程

过程

分配内存:

JS引擎为我们创建的变量、函数分配所需的内存

使用内存:

使用内存是我们代码中明确进行的工作,对内存的读写只不过是对变量的读写

释放内存:

这个步骤也是由JS引擎处理,释放内存之后就可以用于其它目的

堆内存和栈内存

JS引擎在两个地方储存数据:堆内存和栈内存

堆和栈是引擎用于不同目的的两种数据结构

栈:静态内存分配

栈内存是js引擎用来储存静态数据的数据结构,静态数据是在引擎进行编译时知道大小的数据,在JS中,这包含原始值(数字字符串布尔值undefinednull)和指向函数和对象的引用

由于引擎知道数据的大小不会变,所以它为每个值分配固定数量的内存

在执行之前分配内存的过程称为静态内存分配

因为引擎为这些值分配了固定数量的内存,所以原始值的大小是有限制的

这些值和整个栈的限制取决于不同的JS引擎

const male = true
const name = 'PluginsKers'
const age = 17
const adult = true

所有的值都储存在栈中,因为它们都是原始值

堆:动态内存分配

堆内存是JS引擎用于储存对象和函数的空间

与栈内存不同,JS引擎不为这些对象分配数量固定的内存. 相反,将根据需要分配更多的空间,这种方式分配内存也称为动态内存分配

下边是两种储存特性的比较:

原始值和引用objectfunction
大小在编译时已知在运行时知道大小
分配固定数量的内存每个对象没有限制
const person = {
  name: 'PluginsKers',
  age: 17,
};

js在堆中为这个对象分配内存

const hobbies = ['hiking', 'reading'];

数组也是对象,所以它被分配在堆内存当中

let name = 'PluginsKers'; // 为一个字符串分配内存
const age = 24; // 为一个数字分配内存
  
name = 'PluginsDoe'; // 为一个新的字符串分配内存
const firstName = name.slice(0,4); // 为一个新的字符串分配内存

原始值是不可变的,这意味着js不会改变原始值,而是创建一个新值

在JS中的表现

所有的变量首先指向栈,如果它不是原始值,则栈中包含对象的引用

堆内存中没有特定的方式排序,这就是为什么要在栈中保存它的引用

PS: JS在堆中储存对象,在栈中储存原始值和引用

垃圾回收(gc)

现在还有最后一步没有完成:释放内存

就像内存分配一样,JS引擎也会为我们处理这一步,更具体地说垃圾收集器gc负责处理这个问题

一旦JS引擎意识到不再需要给定的变量和函数,它就会释放所占用的内存,这样做的主要问题是:无法确定一些内存是否被需要,这意味着没有一种算法能够在过时的那一刻立即收集不再需要的内存

一些算法很好的逼近了这个问题, 在这里将介绍最常用的方法:引用计数垃圾收集和标记清除法

引用计数的垃圾收集

这是解决问题最简单的近似值,它收集没有引用指向它们的对象

请注意在最后一帧中只有 hobbies 保存在堆中

循环引用

这个算法的问题在于它没有考虑到循环引用,当一个或者多个对象循环引用,但是不能通过代码访问它们时,就会发生这种情况

let son = {
  name: 'Rabbis',
};
  
let dad = {
  name: 'PluginsKers',
}
  
son.dad = dad;
dad.son = son;
  
son = null;
dad = null;

循环引用

因为sondad两个对象相互引用了,所以算法不会释放已分配的内存,但是也无法通过代码访问它们

将它们设置为null并不会使引用计数算法意识到它们不能被使用,因为它们都有被引用

标记清除法

清除标记

标记清除法具有解决循环引用的方案,它不是通过简单的计算给定对象的引用,而是检测它们是否可以从根节点访问

浏览器中的根是windownode中的根是global

该算法将不可访问的对象标记为垃圾,然后清除它们,根对象永远不会被清除

这样循环依赖就不是问题了,上边的示例中dadson对象不能从根节点访问,因此它们都被标记为垃圾,并收集

2012年以来,该算法已在所有现代浏览器中实现。仅对性能和实现进行了改进,而没有对算法的核心思想进行改进。

最后

以上是个人在实战和相关学习中总结的,如有错误,敬请指正!表情

17

评论 (0)

取消