浏览器垃圾回收机制与 Vue 项目内存泄漏场景分析
和其他语言一样,JS 的 GC 策略也无法避免一个问题:GC 时,停止响应其他操作,这是为了安全考虑。而 Javascript 的 GC 在 100ms 甚至以上,对一般的应用还好,但对于 JS 游戏,动画对连贯性要求比较高的应用,就麻烦了。这就是新引擎需要优化的点:避免GC造成的长时间停止响应。 3. GC优化策略 David 大叔主要介绍了2个优化方案,而这也是最主要的2个优化方案了: 分代回收(Generation GC) 这个和Java回收策略思想是一致的,也是V8所主要采用的。目的是通过区分“临时”与“持久”对象;多回收“临时对象”区(young generation),少回收“持久对象”区(tenured generation),减少每次需遍历的对象,从而减少每次GC的耗时。如图: ![]() 这里需要补充的是:对于 tenured generation 对象,有额外的开销:把它从 young generation 迁移到 tenured generation,另外,如果被引用了,那引用的指向也需要修改。这里主要内容可以参考深入浅出Node中关于内存的介绍,很详细~ 2. 增量GC 这个方案的思想很简单,就是“每次处理一点,下次再处理一点,如此类推”。如图: ![]() 这种方案,虽然耗时短,但中断较多,带来了上下文切换频繁的问题。因为每种方案都其适用场景和缺点,因此在实际应用中,会根据实际情况选择方案。比如:低 (对象/s) 比率时,中断执行GC的频率,simple GC更低些;如果大量对象都是长期“存活”,则分代处理优势也不大。 4. Vue 中的内存泄漏问题 JS 程序的内存溢出后,会使某一段函数体永远失效(取决于当时的 JS 代码运行到哪一个函数),通常表现为程序突然卡死或程序出现异常。 这时我们就要对该 JS 程序进行内存泄漏的排查,找出哪些对象所占用的内存没有释放。这些对象通常都是开发者以为释放掉了,但事实上仍被某个闭包引用着,或者放在某个数组里面。 4.1 泄漏点 DOM/BOM 对象泄漏; script 中存在对 DOM/BOM 对象的引用导致; JS 对象泄漏; 通常由闭包导致,比如事件处理回调,导致 DOM 对象和脚本中对象双向引用,这个是常见的泄漏原因; 4.2 代码关注点 主要关注的就是各种事件绑定场景,比如: DOM 中的 addEventLisner 函数及派生的事件监听,比如 Jquery 中的 on 函数,Vue 组件实例的 $on 函数; 其它 BOM 对象的事件监听, 比如 websocket 实例的 on 函数; 避免不必要的函数引用; 如果使用 render 函数,避免在 HTML 标签中绑定 DOM/BOM 事件; 4.3 如何处理 如果在 mounted/created 钩子中使用 JS 绑定了 DOM/BOM 对象中的事件,需要在 beforeDestroy 中做对应解绑处理; 如果在 mounted/created 钩子中使用了第三方库初始化,需要在 beforeDestroy 中做对应销毁处理(一般用不到,因为很多时候都是直接全局 Vue.use); 如果组件中使用了 setInterval,需要在 beforeDestroy 中做对应销毁处理; 4.4 在 vue 组件中处理 addEventListener (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |