内存泄露与垃圾回收机制GC

一、内存泄露

不再使用的内存,没有及时被释放,机会造成内存泄露

二、垃圾回收机制

因为收回过程内存开销比较大,且堵塞其他操作,所以V8引擎会周期性的释放那些不再使用的变量,进而释放内存

1. 全局变量:生命周期较长,直到卸载当前页面才会回收

2. 局部变量:如函数内的变量(排除个别闭包),一旦函数执行完毕,该变量即会被回收

2. 闭包:分为两种,一种是程序自动生成的闭包,会遵循局部变量规则,但手动生成的闭包,V8引擎不会自动回收,需要开发者人为的将变量置为null,才会被回收。后期单独讲解闭包

三、方式

主要分为两种,标记清除和引用计数

1. 标记清除:

变量进入执行上下文时,会打个进入环境的标记,当离开执行环境时,再打个离开环境的标记,在下一个回收周期内,会将离开执行环境的变量进行回收

2. 引用计数:

当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。

相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。如:

function fn() {
    var q = {}; // q 指向对象的引用次数为 1
    var a = q;  // q 指向对象的引用次数加 1,为 2
    var c = q;  // q 指向对象的引用次数再加 1,为 3
    var a = {}; // q 指向对象的引用次数减 1,为 2
}

这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为 0 的值所占用的内存,进而无法刚问引用次数为0的变量。

但该方式会存在一个bug,即循环引用的变量不会被回收,如:

function fn() {
    var q = {};  // q 指向对象的引用次数为 1
    var a = {};  // a 指向对象的引用次数为 1
    q.obj = a;  // a 指向对象的引用次数为 2
    a.obj = q;  // q 指向对象的引用次数为 2
}
fn();

即使fn已经执行完毕,理论上q和a应该会被回收,但由于引用次数不为0,就造成了不会被回收

关注微信公众号,解锁更多技术文章

展开阅读全文

页面更新:2024-04-04

标签:内存   垃圾   变量   局部   函数   标记   次数   机制   对象   方式   环境

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top