js的垃圾回收机制和内存分配

GC垃圾回收机制:

垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

不再使用的变量即指那些局部变量,全局变量的生命周期直到浏览器关闭页面才结束,这时会再清除一次。

局部变量只在函数执行过程中存在,这个过程中会给它们分配内存去储存它们的值,然后在函数中使用,直至函数结束,而闭包是因为在函数外还有对这个变量的引用,所以并不会被垃圾回收机制清除。

标记清除法(常用):

垃圾回收器在运行的时候会给储存在内存里的所有变量都加上标记。然后去掉环境中的变量及被环境中的变量引用的变量的标记。在这之后还有标记的变量将被视为要删除的变量。最后,回收机制运行,销毁这些带标记的值并回收他们所占的内存空间。

例:

    function mark(){
        var a = 10; //被标记进入环境
        var b = 20; //被标记进入环境
      }
      mark();       //执行完毕,a,b被标记离开环境

引用计数法:

跟踪记录每个值被引用的次数。声明一个变量且把一个引用数据类型赋给这个变量的时候,这个变量的引用次数+1,如果同个值再被赋给另外一个变量,引用次数再+1。相反,如果包含对这个值的引用的变量又被赋了另外一个值,它的引用次数就-1。引用次数为0时,将被认为是需要回收的值。

问题:循环引用时会造成互相引用的两个变量引用次数都不会为0,将不会被清除,造成内存泄漏。如果需要解决这种问题,则需要手动结束两个变量的互相引用,将变量设置为null

例:

    function cite(){
        var a = 10; 
        var b = a;  //a被引用,引用次数为1
        var c = a;  //a再次被引用,引用次数为2
        b = {};     //b解除对a的引用,a的引用次数为1
      }

GC机制的缺陷:

GC时会停止响应其他操作。

优化:

分代回收:

与Java的回收策略相似,即将对象分为“临时”与“持久”对象,多回收“临时”对象区,少回收“持久”对象区,这样减少了每次回收时判断遍历的个数,从而减少了每次GC的耗时。

增量回收:

每次处理一点,下次再处理一点,优点是减少了GC的耗时,但中断却较多。


内存分配:

javascript变量可以用来保存两种类型的值,基本类型值(undefined,null,boolean,number,string)和引用类型值(array,function,object)。

  • 基本类型的值在内存中占据固定大小的空间,因此被保存在栈内存中,从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本。
  • 引用类型的值是对象,保存在堆内存中。包含引用类型值的变量实际上包含的不是对象本身,而是一个指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终指向的是同一个对象,所以修改之前的值,之后复制的变量也会被修改,而这是我们不希望的,所以存在深浅复制的问题。js实现深浅复制
  • 栈的优势就是存取速度比堆要快,存放在一级缓存中,仅次于直接位于CPU中的寄存器,但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
  • 堆的优势是可以动态地分配内存大小,存在二级缓存中,生存期也不必事先告诉编译器,垃圾收集器会自动地收走这些不再使用的数据,比如对象和数组是可以无限拓展的,正好放在可以动态分配大小的堆中。但是缺点是由于在运行时动态分配内存,所以存取速度较慢。


猜你喜欢

转载自blog.csdn.net/baibaider/article/details/79740864
今日推荐