JS-垃圾机制

简介

JAVAScript 具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存 。在编写JS的过程中,开发者不用关心内存的问题,所需内存的分配以及无 用内存的回收完全实现了自动管理 。这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变 量,然后释放其占用的内存 。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作 。
内存的生命周期
内存分配:局部变量只在函数执行的过程中存在 。而在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值 。
内存使用:然后在函数中使用这些变量,直至函数执行结束 。
内存回收:此时,局部变量就没有存在的必要了,因此可以释放它们的内存以供将来使用
标记清除
【JS-垃圾机制】JS 中最常用的垃圾收集方式是标记清除(mark-and-sweep),当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境” 。从逻辑上讲,永远不能释放进入环境的变 量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们 。而当变量离开环境时,则将其 标记为“离开环境” 。
由于被清理完的内存是不连续的,所以导致了后续存量大的对象可能无法正常存入内存当中,一般的处理方式都是在垃圾回收后进行整理操作,这种方法也叫 标记整理,整理的过程就是将不连续的内存向一端复制,使不连续的内存连续起来 。目前主流浏览器的 JS 实现使用的都是 标记清除 式的垃圾收集策略(或类似的策略),只不过垃圾收集的时间间隔互有不同
举个funtion example(){ // 此时被标记,进入环境 let a = 10};example(); // 函数执行完毕,此时a被标离开环境,被回收 。// 垃圾收集器 完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间 引用计数
引用计数的含义是跟踪记录每 个值被引用的次数 。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1 。如果同一个值又被赋给另一个变量,则该值的引用次数加 1 。相反,如果包含对这个值引用的变量又取 得了另外一个值,则这个值的引用次数减 1 。当这个值的引用次数变成 0 时,则说明没有办法再访问这 个值了,因而就可以将其占用的内存空间回收回来 。这样,当垃圾收集器下次再运行时,它就会释放那 些引用次数为零的值所占用的内存

JS-垃圾机制

文章插图
引用计数图例
举个function example(){ let a = 1; // a 初始化 count = 0 let b = a; // b引用a,count = 1 let b = 1; // b接触对a的引用,count = 0 。当count重新为0时,内存回收a}手动管理内存
执行中的代码只保存必要的数据 。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个 做法叫做解除引用(dereferencing) 。这一做法适用于大多数全局变量和全局对象的属性 。局部变量会在 它们离开执行环境时自动被解除引用
举个function example(name){ let localPerson = new Object(); localPerson.name = name;}var globalPerson = example("Nicholas"); // 手工解除 globalPerson 的引用globalPerson = null; // 解除globalPerson引用,让值脱离执行环境,垃圾收集器下次运行时便会将其回收 几种常见内存泄露及解决方案
  • 全局变量
原因:一个未声明的变量的引用在全局对象中创建了一个新变量 。在浏览器的环境中,全局对象是window解决办法:添加'use strict'
  • 循环引用
原因:在js的内存管理环境中,对象 A 如果有访问对象 B 的权限,叫做对象 A 引用对象 B 。引用计数的策略是将“对象是否不再需要”简化成“对象有没有其他对象引用到它”,如果没有对象引用这个对象,那么这个对象将会被回收。举个function example() { let obj1 = {};let obj2 = {};obj1.a = obj2; // obj1 引用 obj2obj2.a = obj1; // obj2 引用 obj1 }当函数 example 执行结束后,返回值为 undefined,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1 和 obj2 的引用次数都不为 0,所以他们不会进入回收队列解决方案:不使用时设为null
  • 闭包
闭包会造成对象引用的生命周期脱离当前函数的上下文,如果闭包如果使用不当,可以导致环形引用(circular reference),类似于死锁,只能避免,无法发生之后解决,即使有垃圾回收也还是会内存泄露 。


推荐阅读