日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

深入浅出 JavaScript 内存管理,垃圾回收

發(fā)布時(shí)間:2024/4/13 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入浅出 JavaScript 内存管理,垃圾回收 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)介

本篇文章講解JavaScript 中垃圾回收機(jī)制,內(nèi)存泄漏,結(jié)合一些常遇到的例子,相信各位看完后,會(huì)對(duì)JS 中垃圾回收機(jī)制有個(gè)深入的了解。

我的github,歡迎 star

內(nèi)存生命周期

首先,不管什么程序語(yǔ)言,內(nèi)存生命周期基本是一致的:

  • 分配你所需要的內(nèi)存
  • 使用分配到的內(nèi)存(讀、寫(xiě))
  • 不需要時(shí)將其釋放歸還

?在所有語(yǔ)言中第一和第二部分都很清晰。最后一步在低級(jí)語(yǔ)言中(C語(yǔ)言等)很清晰,但是在像JavaScript 等高級(jí)語(yǔ)言中,這一步是隱藏的、透明的。因?yàn)镴avaScript 具有自動(dòng)垃圾收集機(jī)制(Garbage collected )。在編寫(xiě) JS 時(shí),不需要關(guān)心內(nèi)存使用問(wèn)題,所需內(nèi)存分配以及無(wú)用內(nèi)存的回收完全實(shí)現(xiàn)了自動(dòng)管理。

內(nèi)存泄漏

內(nèi)存泄漏(memory leaks),什么情況下回導(dǎo)致內(nèi)存泄漏?可以簡(jiǎn)單理解為有些代碼本來(lái)要被回收的,但沒(méi)有被回收,還一直占用著操作系統(tǒng)內(nèi)存,從而越積越多,最終會(huì)導(dǎo)致內(nèi)存泄漏(可以理解為,內(nèi)存滿了,就溢出了)。

管理內(nèi)存(Memory Management)

分配給web瀏覽器的可用內(nèi)存數(shù)量通常要比分配給桌面應(yīng)用程序少。這樣做的目的主要是處于安全方面考慮,目的是防止運(yùn)行JS 的網(wǎng)頁(yè)耗盡全部系統(tǒng)內(nèi)存而導(dǎo)致系統(tǒng)崩潰。內(nèi)存限制問(wèn)題不僅會(huì)影響給變量分配內(nèi)存,同時(shí)還會(huì)影響調(diào)用棧以及在一個(gè)線程中能夠同時(shí)執(zhí)行的語(yǔ)句數(shù)量。

因此,確保占用最少的內(nèi)存可以讓頁(yè)面獲得更好的性能。而優(yōu)化內(nèi)存占用的最佳方式,就是為執(zhí)行中的代碼只保存必要的數(shù)據(jù)。一旦數(shù)據(jù)不再有用,最好通過(guò)將其值設(shè)置為 null 來(lái)釋放其引用。這個(gè)方法叫做解除引用。這一做法適用于大多數(shù)的全局變量和全局對(duì)象的屬性。局部變量會(huì)在他們離開(kāi)執(zhí)行環(huán)境時(shí)自動(dòng)被解除引用。

解除一個(gè)值的引用并不意味著自動(dòng)回收改值所占用的內(nèi)存。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運(yùn)行時(shí)將其回收。

標(biāo)記清除(Mark and Sweep)

通常,垃圾收集器(garbage collector)在運(yùn)行時(shí)候會(huì)給儲(chǔ)存在內(nèi)存中的所有變量都加上標(biāo)記。然后,它會(huì)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無(wú)法訪問(wèn)到這些變量了。最后,垃圾收集器完成內(nèi)存清除的工作。

那標(biāo)記清除具體是如何呢?有以下幾種算法:

  • 在JavaScript 中,全局變量(Global)和window 對(duì)象會(huì)一直存在,不會(huì)被垃圾收集器回收;
  • 遞歸所用到的所有(包括變量和方法),都不會(huì)被回收;
  • 所有沒(méi)有被標(biāo)記為“活躍(active)”的,都會(huì)被認(rèn)為是垃圾,收集器釋放會(huì)回收垃圾,并把內(nèi)存還給操作系統(tǒng)。

例子:

例一:

var n = 123; // 給數(shù)值變量分配內(nèi)存var s = "azerty"; // 給字符串分配內(nèi)存// 給對(duì)象及其包含的值分配內(nèi)存 var o = {a: 1,b: null };// 給函數(shù)(可調(diào)用的對(duì)象)分配內(nèi)存 function f(a){return a + 2; }

例二:

function foo(arg) {// 此處bar 是全局變量,window.bar 可以訪問(wèn),所以也不會(huì)被回收bar = "this is a hidden global variable"; } function foo() {// 此處this 代表 windowthis.variable = "potential accidental global"; }

例三:

var someResource = getData(); setInterval(function() {var node = document.getElementById('Node');if(node) {node.innerHTML = JSON.stringify(someResource));} }, 1000);// 上面這段代碼,定時(shí)器setInterval 和 someResource 一直存在,不會(huì)被回收。可以改成下面代碼var element = document.getElementById('button');function onClick(event) {element.innerHtml = 'text'; }element.addEventListener('click', onClick); // 手動(dòng)移除事件監(jiān)聽(tīng)器和變量 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) {// 清除定時(shí)器clearInterval(intervalId);}// 清除變量intervalId = null; }

鏈接觀察垃圾回收是怎么工作的—Google: Watching the GC work

在上面圖片中,可以觀察到,點(diǎn)擊 start 按鈕,內(nèi)存和節(jié)點(diǎn)數(shù)暴增,當(dāng)點(diǎn)擊stop 時(shí),垃圾收集器回收了這些定時(shí)器、變量等,從而釋放了內(nèi)存。

上期博客

  • 重構(gòu)你的JS代碼
  • 一些CSS3動(dòng)畫(huà)

我的github,歡迎star

超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的深入浅出 JavaScript 内存管理,垃圾回收的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。