摘要:可以改成下面代碼手動移除事件監(jiān)聽器和變量例四清除定時器清除變量鏈接觀察垃圾回收是怎么工作的在上面圖片中,可以觀察到,點擊按鈕,內存和節(jié)點數(shù)暴增,當點擊時,垃圾收集器回收了這些定時器變量等,從而釋放了內存。
簡介
本篇文章講解JavaScript 中垃圾回收機制,內存泄漏,結合一些常遇到的例子,相信各位看完后,會對JS 中垃圾回收機制有個深入的了解。
我的github,歡迎 star
內存生命周期首先,不管什么程序語言,內存生命周期基本是一致的:
分配你所需要的內存
使用分配到的內存(讀、寫)
不需要時將其釋放歸還
?在所有語言中第一和第二部分都很清晰。最后一步在低級語言中(C語言等)很清晰,但是在像JavaScript 等高級語言中,這一步是隱藏的、透明的。因為JavaScript 具有自動垃圾收集機制(Garbage collected )。在編寫 JS 時,不需要關心內存使用問題,所需內存分配以及無用內存的回收完全實現(xiàn)了自動管理。
內存泄漏內存泄漏(memory leaks),什么情況下回導致內存泄漏?可以簡單理解為有些代碼本來要被回收的,但沒有被回收,還一直占用著操作系統(tǒng)內存,從而越積越多,最終會導致內存泄漏(可以理解為,內存滿了,就溢出了)。
管理內存(Memory Management)分配給web瀏覽器的可用內存數(shù)量通常要比分配給桌面應用程序少。這樣做的目的主要是處于安全方面考慮,目的是防止運行JS 的網(wǎng)頁耗盡全部系統(tǒng)內存而導致系統(tǒng)崩潰。內存限制問題不僅會影響給變量分配內存,同時還會影響調用棧以及在一個線程中能夠同時執(zhí)行的語句數(shù)量。
因此,確保占用最少的內存可以讓頁面獲得更好的性能。而優(yōu)化內存占用的最佳方式,就是為執(zhí)行中的代碼只保存必要的數(shù)據(jù)。一旦數(shù)據(jù)不再有用,最好通過將其值設置為 null 來釋放其引用。這個方法叫做解除引用。這一做法適用于大多數(shù)的全局變量和全局對象的屬性。局部變量會在他們離開執(zhí)行環(huán)境時自動被解除引用。
解除一個值的引用并不意味著自動回收改值所占用的內存。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運行時將其回收。
標記清除(Mark and Sweep)通常,垃圾收集器(garbage collector)在運行時候會給儲存在內存中的所有變量都加上標記。然后,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記。而在此之后再被加上標記的變量將被視為準備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后,垃圾收集器完成內存清除的工作。
那標記清除具體是如何呢?有以下幾種算法:
在JavaScript 中,全局變量(Global)和window 對象會一直存在,不會被垃圾收集器回收;
遞歸所用到的所有(包括變量和方法),都不會被回收;
所有沒有被標記為“活躍(active)”的,都會被認為是垃圾,收集器釋放會回收垃圾,并把內存還給操作系統(tǒng)。
例子: 例一:var n = 123; // 給數(shù)值變量分配內存 var s = "azerty"; // 給字符串分配內存 // 給對象及其包含的值分配內存 var o = { a: 1, b: null }; // 給函數(shù)(可調用的對象)分配內存 function f(a){ return a + 2; }例二:
function foo(arg) { // 此處bar 是全局變量,window.bar 可以訪問,所以也不會被回收 bar = "this is a hidden global variable"; } function foo() { // 此處this 代表 window this.variable = "potential accidental global"; }例三:
var someResource = getData(); setInterval(function() { var node = document.getElementById("Node"); if(node) { node.innerHTML = JSON.stringify(someResource)); } }, 1000); // 上面這段代碼,定時器setInterval 和 someResource 一直存在,不會被回收。可以改成下面代碼 var element = document.getElementById("button"); function onClick(event) { element.innerHtml = "text"; } element.addEventListener("click", onClick); // 手動移除事件監(jiān)聽器和變量 element.removeEventListener("click", onClick); element.parentNode.removeChild(element);例四:
var intervalId = null, params; function createChunks() { var div, foo, i, str; for (i = 0; i < 20; i++) { div = document.createElement("div"); str = new Array(1000000).join("x"); foo = { str: str, div: div }; div.foo = foo; } } function start() { if (intervalId) { return; } intervalId = setInterval(createChunks, 1000); } function stop() { if (intervalId) { // 清除定時器 clearInterval(intervalId); } // 清除變量 intervalId = null; }
鏈接觀察垃圾回收是怎么工作的—Google: Watching the GC work
在上面圖片中,可以觀察到,點擊 start 按鈕,內存和節(jié)點數(shù)暴增,當點擊stop 時,垃圾收集器回收了這些定時器、變量等,從而釋放了內存。
上期博客重構你的JS代碼
一些CSS3動畫
我的github,歡迎star
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91937.html
摘要:摘要是如何回收內存的深入淺出系列深入淺出第課箭頭函數(shù)中的究竟是什么鬼深入淺出第課函數(shù)是一等公民是什么意思呢深入淺出第課什么是垃圾回收算法最近垃圾回收這個話題非常火,大家不能隨隨便便的扔垃圾了,還得先分類,這樣方便對垃圾進行回收再利用。 摘要: JS是如何回收內存的? 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數(shù)中的this究竟是什么鬼? Jav...
摘要:一前言的垃圾回收機制使用垃圾回收機制來自動管理內存。垃圾回收器只會針對新生代內存區(qū)老生代指針區(qū)以及老生代數(shù)據(jù)區(qū)進行垃圾回收。分別對新生代和老生代使用不同的垃圾回收算法來提升垃圾回收的效率。 V8 實現(xiàn)了準確式 GC,GC 算法采用了分代式垃圾回收機制。因此,V8 將內存(堆)分為新生代和老生代兩部分。 一、前言 V8的垃圾回收機制:JavaScript使用垃圾回收機制來自動管理內存。垃...
摘要:垃圾回收內存管理實踐先通過一個來看看在中進行垃圾回收的過程是怎樣的內存泄漏識別在環(huán)境里提供了方法用來查看當前進程內存使用情況,單位為字節(jié)中保存的進程占用的內存部分,包括代碼本身棧堆。 showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術棧 | https:...
摘要:新生代的對象為存活時間較短的對象,老生代中的對象為存活時間較長或常駐內存的對象。分別對新生代和老生代使用不同的垃圾回收算法來提升垃圾回收的效率。如果指向老生代我們就不必考慮它了。 這篇文章的所有內容均來自 樸靈的《深入淺出Node.js》及A tour of V8:Garbage Collection,后者還有中文翻譯版V8 之旅: 垃圾回收器,我在這里只是做了個記錄和結合 垃圾回收...
摘要:它將堆內存一分為二每一部分空間稱為。以的垃圾回收堆內存為例做一次小的垃圾回收需要毫秒以上做一次非增量式的垃圾回收甚至要秒以上。這是垃圾回收中引起線程暫停執(zhí)行的時間在這樣的時間花銷下應用的性能和響應能力都會直線下降。 我們通常理解的 javascript 垃圾回收機制都停留在表面,會釋放不被引用變量內存,最近在讀《深入淺出node.js》的書,詳細了解了下 v8 垃圾回收的算法,記錄了一...
閱讀 3537·2021-09-10 10:51
閱讀 2507·2021-09-07 10:26
閱讀 2482·2021-09-03 10:41
閱讀 810·2019-08-30 15:56
閱讀 2896·2019-08-30 14:16
閱讀 3488·2019-08-30 13:53
閱讀 2103·2019-08-26 13:48
閱讀 1913·2019-08-26 13:37