1

垃圾回收

  • js的垃圾自动回收机制,就是找到不被使用的值,将其占用的内存释放掉。

引用计数

  • 现代游览器已不在使用引用计数,Ie9以下的游览器仍在使用。
  • 引用计数,即查看对象是否存在指向他的引用,如果没有则释放掉。
var a = { a: 1 };
var c = a;

上面这一段代码,{a:1} 被a,b应用了两次,将 a = null, b = null 时 { a: 1 } 才会被释放掉

  • 这种回收机制无法释放一些无效但是存在引用的对象(循环引用)
function test (){
   var a = { ax: 1 };
   var b = { bx: 2 };
   a.bx = b;
   b.ax = a; 
   ......
}

执行test()时:

理想:test执行开始时候,会给其中定义的变量划分内存空间保存,以备后面的语句使用,等函数执行完毕返回了这些变量被认为无用的了,对应的空间也就收回了,下次执行此函数的时候,所有变量回到初始状态,重新赋值使用。

现实:test执行后,本应该释放的a,b发现a被b引用,b被a引用。他们引用次数大于0不会被垃圾回收,内存泄漏。

下面是一段常用的

var div = document.getElementById('test')
div.onClick = function () { }

div有事件处理函数的引用,同时事件处理函数也有div的引用!(div变量可在函数内被访问) 一个循环引用形成

标记清楚

  1. 简单来说就是根部(全局)触达,凡是不能通过根部找到的将会被释放掉。
  2. 从根部开始访问并标记他们(同时防止用一个对象重复遍历),最后将未有标记的清除掉。

图片描述

内存泄漏

  • 简单来说就是一些不在使用的值,仍占据内存没有被回收掉就会造成内存泄漏。
  • 原因:存在不需要的引用

常见的内存泄漏

意外的全局变量

function () {
  a = 'test'
}

function () {
  this.a = 'test'
}
  • 函数内部用了为声明的变量a或this.a,即 window.a = 'test'
  • 在函数使用变量时,根据需求避免一些非必要的全局声明

遗漏的定时器

var n = 1

setInterval(() => {
  if(n < 2000){
    n++
  }
}, 1000)
  • 当n>=2000后没有清除定时器

DOM操作

<body>
  <button onclick="re()">remove</button>
  <ul id='par' class="p">
    <li id="c">1111</li>
  </ul>
</body>
<script>
  var li = document.getElementById('c');

  function re() {
    // 移除 ul的dom节点
    document.body.removeChild(document.getElementById('par'))
    
    // 通过li查找父节点
    console.log(li.parentNode)
  }
</script>
  • 当声明一个li并指向一个DOM节点后,即使将DOM整个删除(父级),通过这个声明我仍能通过这个引用(li)找回整个已经被删除的DOM树
  • 除必要情况下,DOM操作要做到用后即焚。

闭包

function onclick(){
    let btn = document.getElementById("button");
    obj.onclick=function(){
        //.
    }
}
  • 函数内部定义了一个变量,这个变量的事件引用了内部函数,并且这个事件回调函数的引用外暴了,形成闭包.

D_Q_
483 声望12 粉丝

前端萌萌哒