• 常见的内存泄漏以及解决方案


    一、什么是内存泄漏?

    二、JS引起内存泄漏的原因?

      意外的全局变量

      闭包引用的内存泄漏

      Dom元素的引用没有被释放

      被遗忘的定时器或者回调函数

    三、Vue中引起内存泄漏的原因

      全局变量引起的内存泄漏

      监听在window/body等事件没有解绑

      绑在EventBus的事件没有解绑

    一、什么是内存泄漏?

      系统进程不再用到的内存,没有及时的释放,就叫做内存泄漏。

    二、JS引起内存泄漏的原因?

    1、意外的全局变量

      由于js对没有进行申明的变量会默认是在全局变量上定义的,而系统的全局变量是 window,只有关闭窗口和刷新页面,全局变量才会被释放,如果在一个没有声明的变量上保存了大量的数据,这些数据就会保存在全局变量上,当这些数据没有及时的被回收,就会发生 内存泄漏

    • 没有声明的变量
      function fn(){
        a='hello'
      }
      fn();
    • 使用this申明的变量
      function fn(){
       // 这里的this指向它的调用者,他的调用者是window 
        this.a='hello';
      }
      fn()

      解决方法:
      避免使用没有声明的变量;

      使用 严格模式,在js文件头部或者是函数首行使用严格模式

    2、闭包引用的内存泄漏

       由于闭包可以访问函数内部的变量,让这些变量一直保存在内存中,如果没有及时的清理掉这些变量,就会发生内存泄漏。

    function fn(){
      var a='i am a';
      return function(){
        console.log(a);
      }
    }

      解决方法:将事件处理程序定义在函数的外部

    // bad
    for(var k=0;k<10;k++){
      var t=function(a){
        console.log(a)
      }
      t(k)
    }
    
    // good
    function t(a){
      console.log(a)
    }
    for(var k=0;k<10;k++){
      t(k)
    }
    t=null

    3、Dom元素的引用没有被释放

       虽然在别的地方Dom别删除了,但是对象对这个Dom元素的引用并没有被删除

    var element={
      btn:document.getElementById('btn')
    }
    
    function doSomeThing(){
      element.btn.cilck()
    }
    
    function removeClick(){
      // 虽然移除了dom中的btn元素,但是对象中对btn的引用还是没有被删除
       document.body.removeChild(document.getElementById( 'btn' ))

      解决方法:将element.btn=null

    4、被遗忘的定时器或者回调函数

       定时器中有dom的引用,即使dom删除了,但是定时器还在,所以内存中还是会有这个dom。

    // 定时器模式
    var data=load()
    setTimeout(() => {
      var text=document.getElementById('text')
      if(text){
        text.innerHtml=JSON.stringify(data)
      }
    }, 5000);
    
    // 观察者模式
    var btn=document.getElementById('btn')
    function click(element){
      element.innerHtml='hello'
    }
    btn.addEventListener("click",click);

      解决方法:

    • 手动删除定时器和dom
    • 添加removeEventListener

    三、Vue中引起内存泄漏的原因

       使用VUE开发的SPA应用,更需要关注内存泄漏,因为VUE项目是不会刷新页面的,所以 Vue 应用需要自行清理组件来确保垃圾回收以预期的方式生效。

    1、全局变量引起的内存泄漏

      全局变量在页面切换的时候没有被清空。

    export default {
       mounted() {
         window.test = {
           // 此处在全局window对象中引用了本页面的dom对象
           name:  home ,
           node: document.getElementById( home ),
         }
       },
     }

      解决方法:在页面卸载的时候就将全局变量被清空

    2、监听在window/body等事件没有解绑

       特别注意window.addEventListener之类的事件监听

    <template>
     <div id='home'>这里是首页</div>
    </template>
    <script>
     export default{
       mounted(){
         window.addEventListener(resize,this.func) // window对象调用了home页面的方法
       }
     }
    </script>

      解决方法:在页面销毁的时候,顺便解除应用,释放内存

    mounted(){
      window.addEventListener(resize,this.func)
    }
    beforeDestory(){
      window.removeEventListener(resize,this.func)
    }
  • 相关阅读:
    BOM 事件 navigator浏览器的判断
    闭包
    超简单超实用的走马灯效果实现
    对DOM的增删改查
    SVN版本回退与常用命令总结
    mongodb使用总结
    如何理解 IE 的文档兼容模式
    软件开发编码规范
    第一篇绑定数据 CMS
    关于IIS7.5下的web.config配置的一些问题
  • 原文地址:https://www.cnblogs.com/zhilili/p/14764850.html
Copyright © 2020-2023  润新知