当前位置: 首页 > 后端技术 > Node.js

javascript的垃圾回收机制和内存管理

时间:2023-04-03 23:56:23 Node.js

垃圾回收Javascript不同于C和C++的地方在于它有自动垃圾回收机制,这意味着开发者可以专注于自己的业务,而不必在上面投入太多的精力。内存管理,提高开发效率。所谓垃圾回收就是把那些不再使用的变量找出来,然后释放它占用的内存。为此,垃圾收集器以固定的时间间隔(或代码执行期间的预定收集时间)定期执行此操作。目前,在浏览器中,垃圾回收的实现方式主要有两种:1.标记和清除也是javascript最常用的垃圾回收方式。标记和清除的方式有两个概念:“进入环境”和“离开环境”。“进入环境”是指变量进入执行的环境。“离开环境”是指变量完成任务,离开执行环境。垃圾收集器在运行时会标记所有存储在内存中的变量。然后它剥离环境中的变量和环境中变量引用的变量。之后被标记的变量将被视为要删除的变量,因为环境中的变量无法再访问这些变量。最后,垃圾回收器完成内存清理,销毁那些标记的值,回收它们占用的内存空间。2.引用计数引用计数的意义就是跟踪记录每个值被引用的次数。当一个变量被声明并且引用类型的值赋给该变量时,这个值的引用计数为1。如果相同的值赋给另一个变量,该值的引用计数加1。反之,如果包含对该值的引用的变量取了另一个值,该值的引用计数减1。当对该值的引用数变为0时,意味着无法访问该值,因此它占用的内存空间可以被恢复。这样,下次垃圾收集器运行时,就会释放引用计数为零的值占用的内存。这种机制在js中其实并不常用,因为这种机制会造成循环引用问题。“循环引用”是指对象A包含一个指向对象B的指针,对象B也包含一个指向对象A的指针。对于像js这种有自动回收机制的语言,需要额外手动释放内存,其实并不友好。例如,在下面的例子中:functiongarbage(){varA=newObject();变量B=新对象();A.属性=B;B.property=A;}由于对象A和B相互引用,引用数为2,所以其占用的内存无法自动释放。这种类型的引用计数被用在IE的BOM和DOM中。IE9之后,微软改用markclear方式管理内存,从而避免了两种方式并存。内存管理与其他桌面程序相比,系统分配给浏览器的内存相对较少。这主要是出于安全考虑,防止运行JavaScript的网页耗尽所有系统内存导致系统崩溃。.内存限制问题不仅会影响内存分配给变量,还会影响调用堆栈和线程中可以同时执行的语句数。因此,确保使用最少的内存量可以提高页面的性能。优化内存使用的最佳方法是只保存执行代码所需的数据。一旦数据不再有用,最好通过将其值设置为null来释放其引用——这种做法称为解除引用。这种做法适用于大多数全局变量和全局对象的属性。局部变量在离开执行环境时会自动取消引用。functioncreatePerson(name){varlocalPerson=newObject();localPerson.name=姓名;}varglobalPerson=createPerson("Nicholas");//手动解引用globalPersonglobalPerson=null;但是,取消引用一个值并不意味着自动回收该值占用的内存。取消引用的真正作用是从执行环境中获取值,以便下次垃圾收集器运行时可以回收它。总结JavaScript是一种具有自动垃圾回收机制的编程语言,开发者不必关心内存的分配和回收。JavaScript的垃圾回收套路可以总结如下。?超出范围的值将被自动标记为可回收,因此将在垃圾回收期间被删除。?“标记清除”是目前主流的垃圾回收算法。这个算法的思路是标记当前没有被使用的值,然后回收它的内存。?另一种垃圾收集算法是“引用计数”,该算法的思想是跟踪所有值被引用的次数。目前没有一个JavaScript引擎使用这个算法;但是,在IE中访问非本机JavaScript对象(例如DOM元素)时,它仍然会导致问题。?当代码中存在循环引用时,“引用计数”算法会导致问题。?解除引用变量不仅有助于消除循环引用,还有助于垃圾回收。为了保证高效的内存回收,未使用的全局对象、全局对象属性、循环引用变量应该及时解引用。---参考《JavaScript高级程序设计第3版》