js垃圾回收机制和内存泄露那些事

一、内存垃圾回收的意义:

        在不需要字符串、对象的时候,要释放其所占的内存,否则系统中的内存有限,占用太多会造成系统奔溃。

二、垃圾回收的机制:

        js会自动回收垃圾内存。

        垃圾回收:找出那些不再继续使用的变量,释放其占用的内存。

        js会按照固定的时间间隔周期性的执行垃圾回收的操作。

        全局变量的的生命周期会知道浏览器关闭结束,也就是说全局变量不会被当成垃圾回收。

三、怎么回收:标记清除、引用计数

        1) 标记清除  (变量)

                目前最常用的垃圾回收机制,也是当前浏览器才用的机制。

                原理:

                标记清除中有两个重要的概念“进入环境”、“离开环境”。“进入环境”:是变量进入执行环境,“离开环境”:是变量完成任务,离开执行环境。

                当声明一个变量时,这个变量就是进入的执行环境,浏览器给加“进入环境”的标记,当离开执行环境时,浏览器给它加“离开环境”的标记。并且回收。

                流程:

                1. 垃圾收集器在运行的时候给所有内存中的变量打上标记。

                2. 去掉环境中的变量以及被环境中的变量引用的变量的标记。

                3. 那些还存在标记的变量则被视为准备删除的变量。

                4. 最后垃圾收集器会执行清除内存的工作,销毁那些带标记的值并回收他们占用的内存。

        2) 引用计数

                跟踪记录每个值的引用次数  (值)

                流程:

                1. 声明一个变量,并给这个变量赋值,这个值的引用次数就是1

                2. 同一个值被赋给另一个变量,这个值的引用次数+1

                3. 变量的值被更改了 那原本那个值的引用次数-1

                4. 引用次数为0时,说明没办法访问这个值了

                5. 垃圾收集器下一次运行时,会释放引用次数为0的值所占的内存

                这个流程潜在一个问题:循环引用,则引用次数不会为0,将不能被自动回收了。

                循环引用:是指A中包含指向对象B的指针,而对象B中也包含一个指向对象A的引用。

                  Eg.

                       function ftc(){

                           var A = new Object();

                           var B = new Object();

                           A.property = B;

                           B.property = A;

                       }

四、内存泄露的原因

        js虽然有自动回收机制,但是还是有些情况会造成内存泄漏:

        1. 全局变量不会被自动回收

                function foo(){

                    this.bar2 = "默认绑定this指向全局"  //全局变量 == window.bsr2

                    bar = "全局变量"  // 没有var声明的变量也是全局变量 == window.bar

                }

                foo();

                解决办法:在函数内使用严格模式or细心一点

                function foo(){

                    "use strict"

                    this.bar2 = "默认绑定this指向全局"  //全局变量 == window.bsr2

                    bar = "全局变量"  // 没有var声明的变量也是全局变量 == window.bar

                }

                foo();

2. 当不需要setInterval或者setTimeout时,定时器没有被清除。定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄露。

var someResource = getData();

setInterval(function(){

var node = document.getElementById("id");

if(node){

node.innerHTML = JSON.stringify(someResource);

//定时器也没有被清除

}

// node、someResource 存储了大量数据 无法回收

},1000)

解决办法:定时器结束时,手动清除定时器。

3. 循环引用,上文提到。

  解决办法:手动清除变量,释放内存。

4. 没有清除的DOM元素引用

var refV = document.getElementById("ID");

document.body.removeChild(refV);//页面上dom删除了

console.log(refV);//能输出值。所以虽然在页面上dom删除了,但在js中 这个dom的变量还在 没有被回收

refV = null;//解决办法 手动清除

console.log(refV);//可以看到已经被清除了

5. 闭包引起的内存泄漏:闭包实际上非常容易造成JavaScript对象和DOM对象的隐蔽循环引用

  解决办法:将事件处理函数定义在外部,解除闭包;或者在定义事件处理函数的外部函数中,删除对dom的引用,手动回收。

  Eg.1   

  function ex(){

  var element = document.getElementById("div1");  // 1

  element.onclick = function(){

  console.log("this is event"); // 2

  }

  }

  ex();


  以上函数ex中,用匿名函数创建了一个闭包

  第1处:js对象 element 引用了一个dom对象    JS(element) ----> DOM(div1)

  第2处:dom对象的onclick属性引用了一个匿名函数,这形成一个闭包,这个匿名函数可以引用整个ex内的所有对象,包括element DOM(div1.onclick) ---->JS(element)

  由此形成了JavaScript对象和DOM对象的隐蔽循环引用。

  解决办法:

  function ex(){

  var element = document.getElementById("div1");  // 1

  element.onclick = function(){

  console.log("this is event"); // 2

  }

  element = null; //添加的语句 删除对dom的引用,手动回收

  }

Eg.2

function ev(){

var element = document.getElementById("div2")

var myName = "lili"

element.onclick = function(){

console.log(myName)

}

}

ev();

由于js中只有函数才具有独立的作用域。

以上函数ev中,onclick引用的匿名函数去访问myName的时候,发现自身作用域中没有这个myName变量,

所以需要去访问父作用域中去调用这个myName变量,形成了闭包,所以myName这个变量会一直存在。

myName这个变量在onclick事件运行之后还会顽固的存在在内存中。

解决办法是运行完成后手动清除 myName = null

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容