摘要:可以改成下面代码手动移除事件监听器和变量例四清除定时器清除变量链接观察垃圾回收是怎么工作的在上面图片中,可以观察到,点击按钮,内存和节点数暴增,当点击时,垃圾收集器回收了这些定时器变量等,从而释放了内存。
简介
本篇文章讲解JavaScript 中垃圾回收机制,内存泄漏,结合一些常遇到的例子,相信各位看完后,会对JS 中垃圾回收机制有个深入的了解。
我的github,欢迎 star
内存生命周期首先,不管什么程序语言,内存生命周期基本是一致的:
分配你所需要的内存
使用分配到的内存(读、写)
不需要时将其释放归还
在所有语言中第一和第二部分都很清晰。最后一步在低级语言中(C语言等)很清晰,但是在像JavaScript 等高级语言中,这一步是隐藏的、透明的。因为JavaScript 具有自动垃圾收集机制(Garbage collected )。在编写 JS 时,不需要关心内存使用问题,所需内存分配以及无用内存的回收完全实现了自动管理。
内存泄漏内存泄漏(memory leaks),什么情况下回导致内存泄漏?可以简单理解为有些代码本来要被回收的,但没有被回收,还一直占用着操作系统内存,从而越积越多,最终会导致内存泄漏(可以理解为,内存满了,就溢出了)。
管理内存(Memory Management)分配给web浏览器的可用内存数量通常要比分配给桌面应用程序少。这样做的目的主要是处于安全方面考虑,目的是防止运行JS 的网页耗尽全部系统内存而导致系统崩溃。内存限制问题不仅会影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量。
因此,确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用。这个方法叫做解除引用。这一做法适用于大多数的全局变量和全局对象的属性。局部变量会在他们离开执行环境时自动被解除引用。
解除一个值的引用并不意味着自动回收改值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
标记清除(Mark and Sweep)通常,垃圾收集器(garbage collector)在运行时候会给储存在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除的工作。
那标记清除具体是如何呢?有以下几种算法:
在JavaScript 中,全局变量(Global)和window 对象会一直存在,不会被垃圾收集器回收;
递归所用到的所有(包括变量和方法),都不会被回收;
所有没有被标记为“活跃(active)”的,都会被认为是垃圾,收集器释放会回收垃圾,并把内存还给操作系统。
例子: 例一:var n = 123; // 给数值变量分配内存 var s = "azerty"; // 给字符串分配内存 // 给对象及其包含的值分配内存 var o = { a: 1, b: null }; // 给函数(可调用的对象)分配内存 function f(a){ return a + 2; }例二:
function foo(arg) { // 此处bar 是全局变量,window.bar 可以访问,所以也不会被回收 bar = "this is a hidden global variable"; } function foo() { // 此处this 代表 window this.variable = "potential accidental global"; }例三:
var someResource = getData(); setInterval(function() { var node = document.getElementById("Node"); if(node) { node.innerHTML = JSON.stringify(someResource)); } }, 1000); // 上面这段代码,定时器setInterval 和 someResource 一直存在,不会被回收。可以改成下面代码 var element = document.getElementById("button"); function onClick(event) { element.innerHtml = "text"; } element.addEventListener("click", onClick); // 手动移除事件监听器和变量 element.removeEventListener("click", onClick); element.parentNode.removeChild(element);例四:
var intervalId = null, params; function createChunks() { var div, foo, i, str; for (i = 0; i < 20; i++) { div = document.createElement("div"); str = new Array(1000000).join("x"); foo = { str: str, div: div }; div.foo = foo; } } function start() { if (intervalId) { return; } intervalId = setInterval(createChunks, 1000); } function stop() { if (intervalId) { // 清除定时器 clearInterval(intervalId); } // 清除变量 intervalId = null; }
链接观察垃圾回收是怎么工作的—Google: Watching the GC work
在上面图片中,可以观察到,点击 start 按钮,内存和节点数暴增,当点击stop 时,垃圾收集器回收了这些定时器、变量等,从而释放了内存。
上期博客重构你的JS代码
一些CSS3动画
我的github,欢迎star
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91937.html
摘要:摘要是如何回收内存的深入浅出系列深入浅出第课箭头函数中的究竟是什么鬼深入浅出第课函数是一等公民是什么意思呢深入浅出第课什么是垃圾回收算法最近垃圾回收这个话题非常火,大家不能随随便便的扔垃圾了,还得先分类,这样方便对垃圾进行回收再利用。 摘要: JS是如何回收内存的? 《JavaScript深入浅出》系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? Jav...
摘要:一前言的垃圾回收机制使用垃圾回收机制来自动管理内存。垃圾回收器只会针对新生代内存区老生代指针区以及老生代数据区进行垃圾回收。分别对新生代和老生代使用不同的垃圾回收算法来提升垃圾回收的效率。 V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制。因此,V8 将内存(堆)分为新生代和老生代两部分。 一、前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存。垃...
摘要:垃圾回收内存管理实践先通过一个来看看在中进行垃圾回收的过程是怎样的内存泄漏识别在环境里提供了方法用来查看当前进程内存使用情况,单位为字节中保存的进程占用的内存部分,包括代码本身栈堆。 showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技术栈 | https:...
摘要:新生代的对象为存活时间较短的对象,老生代中的对象为存活时间较长或常驻内存的对象。分别对新生代和老生代使用不同的垃圾回收算法来提升垃圾回收的效率。如果指向老生代我们就不必考虑它了。 这篇文章的所有内容均来自 朴灵的《深入浅出Node.js》及A tour of V8:Garbage Collection,后者还有中文翻译版V8 之旅: 垃圾回收器,我在这里只是做了个记录和结合 垃圾回收...
摘要:它将堆内存一分为二每一部分空间称为。以的垃圾回收堆内存为例做一次小的垃圾回收需要毫秒以上做一次非增量式的垃圾回收甚至要秒以上。这是垃圾回收中引起线程暂停执行的时间在这样的时间花销下应用的性能和响应能力都会直线下降。 我们通常理解的 javascript 垃圾回收机制都停留在表面,会释放不被引用变量内存,最近在读《深入浅出node.js》的书,详细了解了下 v8 垃圾回收的算法,记录了一...
阅读 3507·2021-09-10 10:51
阅读 2483·2021-09-07 10:26
阅读 2455·2021-09-03 10:41
阅读 787·2019-08-30 15:56
阅读 2864·2019-08-30 14:16
阅读 3465·2019-08-30 13:53
阅读 2069·2019-08-26 13:48
阅读 1896·2019-08-26 13:37