JS系列之垃圾回收機(jī)制,內(nèi)存泄漏,閉包是什么意思-創(chuàng)新互聯(lián)

JS系列之垃圾回收機(jī)制,內(nèi)存泄漏,閉包是什么意思?這個(gè)問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個(gè)問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、萬柏林網(wǎng)絡(luò)推廣、小程序制作、萬柏林網(wǎng)絡(luò)營(yíng)銷、萬柏林企業(yè)策劃、萬柏林品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供萬柏林建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:muchs.cn

垃圾回收機(jī)制

前面一篇博客主要講解了內(nèi)存的分配和使用(棧內(nèi)存與堆內(nèi)存,深拷貝與淺拷貝),使用完了以后,當(dāng)然是要將不使用的內(nèi)存歸還,就像將手機(jī)上不使用的軟件從后臺(tái)清除,可以提升手機(jī)的運(yùn)行速度,不然越來越多,遲早會(huì)卡, JS 也是一樣的。

每隔一段時(shí)間, JS垃圾收集器都會(huì)對(duì)變量進(jìn)行“巡邏”,就和保安巡邏園區(qū)一樣,讓不相干的人趕緊走。當(dāng)一個(gè)變量不被需要了以后,它就會(huì)把這個(gè)變量所占用的內(nèi)存空間所釋放,這個(gè)過程就叫做垃圾回收

JS 的垃圾回收算法分為兩種,引用計(jì)數(shù)法和標(biāo)記清除法

  • 引用計(jì)數(shù)法

    引用計(jì)數(shù)法是最初級(jí)的垃圾回收算法,已經(jīng)被現(xiàn)代瀏覽器所淘汰了。在學(xué)習(xí)引用計(jì)數(shù)法之前,需要首先對(duì)引用有一定的概念,你可以認(rèn)為它就是對(duì)當(dāng)前變量所指向的那塊內(nèi)存地址的描述,有點(diǎn)類似于JS引用數(shù)據(jù)類型的內(nèi)存指向的概念,先來看一行代碼:

    var obj={name:'jack'};復(fù)制代碼

    當(dāng)我們?cè)诮o obj 賦值的同時(shí),其實(shí)就創(chuàng)建了一個(gè)指向該變量的引用,引用計(jì)數(shù)為1,在引用計(jì)數(shù)法的機(jī)制下,內(nèi)存中的每一個(gè)值都會(huì)對(duì)應(yīng)一個(gè)引用計(jì)數(shù)

    而當(dāng)我們給 obj 賦值為 null時(shí),這個(gè)變量就變成了一塊沒用的內(nèi)存,那么此時(shí), obj 的引用計(jì)數(shù)將會(huì)變成 0,它將會(huì)被垃圾收集器所回收,也就是 obj 所占用的內(nèi)存空間將會(huì)被釋放

    我們知道,函數(shù)作用域的生命周期是很短暫的,在函數(shù)執(zhí)行完畢之后,里面的變量基本是沒用的變量了,不清除的后果就是該內(nèi)存垃圾沒有被釋放,依然霸占著原有的內(nèi)存不松手,就會(huì)容易引發(fā)內(nèi)存泄漏,先來看一段代碼以及運(yùn)行結(jié)果:

    function changeName(){   var obj1={};   var obj2={};
       
       obj1.target=obj2;
       obj2.target=obj1;
       obj1.age=15;   console.log(obj1.target);   console.log(obj2.target);
    }
    
    changeName();復(fù)制代碼
    我們可以看到, obj1.targetobj2.target 存在互相引用的情況,因?yàn)樵诟淖?obj1.age 的同時(shí),obj1.target.ageobj2.target.age 也同時(shí)都被影響到了,它們所指向的引用計(jì)數(shù)是一致的

    在函數(shù)執(zhí)行完畢的時(shí)候, obj1obj2 還是活的好好地,因?yàn)?obj1.targetobj2.target 的引用計(jì)數(shù)在執(zhí)行完畢之后,仍然是 1 ,明明函數(shù)執(zhí)行完畢,但是這種垃圾依然存在,這種函數(shù)定義多了,內(nèi)存泄漏也會(huì)是無法避免的

  • 標(biāo)記清除法

    上面的引用計(jì)數(shù)法的弊端已經(jīng)很明顯了,那么,現(xiàn)在所要說的標(biāo)記清除法就不存在這樣子的問題。因?yàn)樗捎玫呐袛鄻?biāo)準(zhǔn)是看這個(gè)對(duì)象是否可抵達(dá),它主要分為兩個(gè)階段,標(biāo)記階段清除階段:

    • 標(biāo)記階段

      垃圾收集器會(huì)從根對(duì)象(Window對(duì)象)出發(fā),掃描所有可以觸及的對(duì)象,這就是所謂的可抵達(dá)

    • 清除階段 在掃描的同時(shí),根對(duì)象無法觸及(不可抵達(dá))的對(duì)象,就是被認(rèn)為不被需要的對(duì)象,就會(huì)被當(dāng)成垃圾清除

    現(xiàn)在再來看下上面的代碼

    function changeName(){    var obj1={};  var obj2={};
      
      obj1.target=obj2;
      obj2.target=obj1;
      obj1.age=15;  console.log(obj1.target);  console.log(obj2.target);
    }
    
    changeName();復(fù)制代碼

    在函數(shù)執(zhí)行完畢之后,函數(shù)的聲明周期結(jié)束,那么現(xiàn)在,從 Window對(duì)象 出發(fā), obj1obj2 都會(huì)被垃圾收集器標(biāo)記為不可抵達(dá),這樣子的情況下,互相引用的情況也會(huì)迎刃而解。

內(nèi)存泄漏

該釋放的內(nèi)存垃圾沒有被釋放,依然霸占著原有的內(nèi)存不松手,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致性能惡化,系統(tǒng)崩潰等嚴(yán)重后果,這就是所謂的內(nèi)存泄漏

閉包

  • 定義與特性

    閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。至于為什么有權(quán)訪問,主要是因?yàn)樽饔糜蚯短鬃饔糜?,也就是所謂的作用域鏈,關(guān)于作用域鏈不清楚的可以看我的第一篇博客一文搞懂JS系列(一)之編譯原理,作用域,作用域鏈,變量提升,暫時(shí)性死區(qū),就是因?yàn)樽饔糜蜴湹拇嬖冢?strong>內(nèi)部函數(shù)才可以訪問外部函數(shù)中定義的變量 ,作用域鏈?zhǔn)窍蛲獠幌騼?nèi)的,探出頭去,向外查找,而不是看著鍋里,所以外部函數(shù)是無法訪問內(nèi)部函數(shù)定義的變量的。并且,還有一個(gè)特性就是將閉包內(nèi)的變量始終保持在內(nèi)存中。

    前面的作用域向外不向內(nèi),這里就不再做過多解釋了,我們主要來看我后面說的特性,那就是閉包內(nèi)的變量始終保存在內(nèi)存中

    來看一下阮一峰教程當(dāng)中的一個(gè)例子

     function f1(){     var n=999;
    
         nAdd=function(){n+=1}     function f2(){         console.log(n);
         }     return f2;
    
     } var result=f1();     //等同于return f2();
    
     result(); // 999
    
     nAdd();
    
     result(); // 1000
     nAdd();
    
     result(); // 1000復(fù)制代碼

    從輸出結(jié)果就可以看得出來,這個(gè)變量 n 就一直保存在內(nèi)存中,那么,為什么會(huì)這樣子呢,我們現(xiàn)在就來逐步地分析代碼

    ① 首先 f1() 作為 f2() 的父函數(shù),根據(jù)作用域鏈的規(guī)則, nAdd() 方法以及 f2() 方法中可以正常訪問到 n 的值

    f2() 被賦予了一個(gè)全局變量,可能這里大家就會(huì)開始產(chǎn)生疑惑了,這個(gè) f2() 不是好好地定義在了 f1() 函數(shù)中嗎,這不是扯淡嗎,那么,先看下面的這句 var result=f1(); ,這個(gè) result 很明顯是被賦予了一個(gè)全局變量,這應(yīng)該是沒有任何爭(zhēng)議的,那么,接著來看這個(gè) f1() ,可以看到最后,是一句 return f2; ,看到這里,想必大家也已經(jīng)想明白了,這個(gè) f2() 被賦予了一個(gè)全局變量

    ③ 已經(jīng)明白了上面的這一點(diǎn)以后,根據(jù)上面垃圾回收機(jī)制所提及到的標(biāo)記清除法,這個(gè) f2() 始終是可以被根對(duì)象 Window 訪問到的,所以 f2 將始終存在于內(nèi)存之中,而 f2 是依賴于 f1 ,因此 f1 也將始終存在于內(nèi)存當(dāng)中,那么, n 的值也就自然始終存在于內(nèi)存當(dāng)中啦

    ④ 還有一點(diǎn)需要注意的就是為什么我們可以直接執(zhí)行 nAdd() ,這是因?yàn)樵?nAdd() 的前面沒有使用 var ,因此 nAdd() 是一個(gè)全局函數(shù)而不是局部函數(shù)。

    感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)JS系列之垃圾回收機(jī)制,內(nèi)存泄漏,閉包是什么意思大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。

分享名稱:JS系列之垃圾回收機(jī)制,內(nèi)存泄漏,閉包是什么意思-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://muchs.cn/article26/dejejg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、小程序開發(fā)網(wǎng)站收錄、網(wǎng)站策劃、ChatGPT、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作