什么是内存泄漏 ? 什么原因产生的? 如何解决?

内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使
用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间
使用完毕之后未回收)即所谓内存泄漏。
哪些操作会造成内存泄漏?
1、垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的
引用数量为 0(没有其他对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象的
内存即可回收
2、setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏
3、闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
内存泄漏的解决方式
       
1、global variables:对未声明的变量的引用在全局对象内创建一个新变量。在浏览器中,全
局对象就是 window。
        
function foo(arg) {
      bar = "some text";// 等同于 window.bar = 'some text';
    }
1.1)解决:
        1.1.1)创建意外的全局变量
   function foo() {
      this.var1 = "potential accident";
    }
        1.1.2)可以在 JavaScript 文件开头添加 “use strict”,使用严格模式。这样在严格模式 下解析 JavaScript 可以防止意外的全局变量
        1.1.3)在使用完之后,对其赋值为 null 或者重新分配
1.2)被忘记的 Timers 或者 callbacks  在 JavaScript 中使用 setInterval 非常常见 大多数库都会提供观察者或者其它工具来处理回调函数,在他们自己的实例变为不可达时, 会让回调函数也变为不可达的。对于 setInterval,下面这样的代码是非常常见的:
<script>
    var serverData = loadData();
    setInterval(function () {
      var renderer = document.getElementById("renderer");
      if (renderer) {
        renderer.innerHTML = JSON.stringify(serverData);
      }
    }, 5000); //This will be executed every ~5 seconds.
</script>
这个例子阐述着 timers 可能发生的情况:计时器会引用不再需要的节点或数据
1.3)闭包:一个可以访问外部(封闭)函数变量的内部函数 JavaScript 开发的一个关键方面就是闭包:一个可以访问外部(封闭)函数变量的内部函数。 由于 JavaScript 运行时的实现细节,可以通过以下方式泄漏内存:
<script>
    var theThing = null;
    var replaceThing = function () {
      var originalThing = theThing;
      var unused = function () {
        if (originalThing) // a reference to 'originalThing'
        console.log("hi");
      };
      theThing = {
        longStr: new Array(1000000).join("*"),
        someMethod: function () {
          console.log("message");
        },
      };
    };
    setInterval(replaceThing, 1000);
</script>
1.4)DOM 引用
有时候,在数据结构中存储 DOM 结构是有用的。假设要快速更新表中的几行内容。将每行 DOM 的引用存储在字典或数组中可能是有意义的。当这种情况发生时,就会保留同一 DOM 元素的两份引用:一个在 DOM 树种,另一个在字典中。如果将来某个时候你决定要删除这些行,则需要让两个引用都不可达
<script>
    var elements = {
      button: document.getElementById("button"),
      image: document.getElementById("image"),
    };
    function doStuff() {
      elements.image.src = "http://example.com/image_name.png";
    }
    function removeImage() {
      // The image is a direct child of the body element.
      document.body.removeChild(document.getElementById("image"));
      // At this point, we still have a reference to #button in the
      //global elements object. In other words, the button element is
      //still in memory and cannot be collected by the GC.
    }
</script>

  • 4
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值