日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

你的 JavaScript 正在泄漏內(nèi)存而你卻不知道

來源: 責(zé)編: 時(shí)間:2023-10-23 17:05:30 297觀看
導(dǎo)讀內(nèi)存泄漏可以被視為你家中的水泄漏;雖然一開始小滴水可能看起來不是什么大問題,但隨著時(shí)間的推移,它們可能會造成嚴(yán)重的損害。同樣,在JavaScript中,當(dāng)不再需要的對象沒有從內(nèi)存中釋放時(shí),就會發(fā)生內(nèi)存泄漏。隨著時(shí)間的推移,這

ge628資訊網(wǎng)——每日最新資訊28at.com

內(nèi)存泄漏可以被視為你家中的水泄漏;雖然一開始小滴水可能看起來不是什么大問題,但隨著時(shí)間的推移,它們可能會造成嚴(yán)重的損害。ge628資訊網(wǎng)——每日最新資訊28at.com

同樣,在JavaScript中,當(dāng)不再需要的對象沒有從內(nèi)存中釋放時(shí),就會發(fā)生內(nèi)存泄漏。隨著時(shí)間的推移,這種累積的內(nèi)存使用可以減慢甚至崩潰你的應(yīng)用程序。ge628資訊網(wǎng)——每日最新資訊28at.com

垃圾收集器的角色

在編程領(lǐng)域,尤其是在處理 JavaScript 等語言時(shí),內(nèi)存管理至關(guān)重要。幸運(yùn)的是,JavaScript 內(nèi)置了一個名為 "垃圾回收器"(GC)的機(jī)制來幫助實(shí)現(xiàn)這一目標(biāo)。想象一下,一個勤勞的清潔工會定期清掃你的房子,撿起任何不用的物品并丟棄,以保持整潔。ge628資訊網(wǎng)——每日最新資訊28at.com

垃圾回收器會定期檢查不再需要或不再可訪問的對象,并釋放它們占用的內(nèi)存。在理想情況下,它可以無縫運(yùn)行,確保未使用的內(nèi)存無需任何人工干預(yù)即可回收。然而,就像我們的清潔工有時(shí)可能會忽略隱藏角落里的閑置物品一樣,垃圾回收器也可能會遺漏因引用而無意中保持存活的對象,從而導(dǎo)致內(nèi)存泄漏。這就是為什么了解內(nèi)存管理的細(xì)微差別并注意潛在的隱患對于任何開發(fā)人員來說都至關(guān)重要:ge628資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,讓我們來看看哪些因素會導(dǎo)致應(yīng)用程序內(nèi)存泄漏:ge628資訊網(wǎng)——每日最新資訊28at.com

1、全局變量

在 JavaScript 中,最高級別的作用域是全局作用域。在此作用域中聲明的變量可從代碼中的任何地方訪問,這可能很方便,但也有風(fēng)險(xiǎn)。對這些變量的不當(dāng)管理可能會導(dǎo)致意外的內(nèi)存保留。ge628資訊網(wǎng)——每日最新資訊28at.com

原因是什么?當(dāng)一個變量在未使用 let 、 const 或 var 聲明的情況下被錯誤賦值時(shí),它就會成為一個全局變量。此類變量駐留在全局作用域中,除非顯式刪除,否則會在應(yīng)用程序的整個生命周期中持續(xù)存在。ge628資訊網(wǎng)——每日最新資訊28at.com

例如:假設(shè)你正在創(chuàng)建一個計(jì)算矩形面積的函數(shù):ge628資訊網(wǎng)——每日最新資訊28at.com

function calculateArea(width, height) {  area = width * height; // 誤地創(chuàng)建全局變量“area”  return area;}calculateArea(10, 5);

這里, area 變量無意中被全局化,因?yàn)樗鼪]有與 let 、 const 或 var 一起聲明。這意味著函數(shù)執(zhí)行后, area 仍然可以訪問并占用內(nèi)存:ge628資訊網(wǎng)——每日最新資訊28at.com

console.log(area); // Outputs: 50

避免:最佳做法是始終使用 let 、 const 或 var 聲明變量,以確保它們具有正確的作用域,不會無意中成為全局變量。此外,如果你有意使用全局變量,請確保它們對于全局訪問是必不可少的,并有意識地管理它們的生命周期。ge628資訊網(wǎng)——每日最新資訊28at.com

修改上述示例以正確對 area 變量進(jìn)行作用域設(shè)置:ge628資訊網(wǎng)——每日最新資訊28at.com

function calculateArea(width, height) {  let area = width * height;   return area;}calculateArea(10, 5);

現(xiàn)在,在函數(shù)執(zhí)行后, area 變量在函數(shù)之外不可訪問,并且在函數(shù)執(zhí)行后將被正確垃圾回收。 定時(shí)器和回調(diào)ge628資訊網(wǎng)——每日最新資訊28at.com

2、定時(shí)器和回調(diào)函數(shù)

JavaScript提供了內(nèi)置函數(shù),允許在特定的時(shí)間段后異步執(zhí)行代碼(使用 setTimeout)或以規(guī)律的間隔執(zhí)行(使用 setInterval)。盡管它們非常強(qiáng)大,但如果沒有正確管理,它們可能無意中導(dǎo)致內(nèi)存泄漏。ge628資訊網(wǎng)——每日最新資訊28at.com

原因:如果一個間隔或超時(shí)引用了一個對象,只要定時(shí)器還在運(yùn)行,它就可以保持該對象在內(nèi)存中,即使應(yīng)用程序的其他部分不再需要該對象。ge628資訊網(wǎng)——每日最新資訊28at.com

示例:

假設(shè)你有一個表示用戶數(shù)據(jù)的對象,并設(shè)置一個間隔每5秒更新這些數(shù)據(jù):ge628資訊網(wǎng)——每日最新資訊28at.com

let userData = {  name: "John",  age: 25};let intervalId = setInterval(() => {  // 每5秒更新userData  userData.age += 1;}, 5000);

現(xiàn)在,如果某個時(shí)刻你不再需要更新userData,但忘記清除間隔,它會繼續(xù)運(yùn)行,阻止 userData 被垃圾回收。ge628資訊網(wǎng)——每日最新資訊28at.com

避免方法:關(guān)鍵是在不需要定時(shí)器時(shí)始終停止它們。如果你完成了一個間隔或超時(shí),使用clearInterval()或clearTimeout()分別清除它們。ge628資訊網(wǎng)——每日最新資訊28at.com

繼續(xù)上面的示例,如果你決定不再需要更新 userData,你可以這樣清除間隔:ge628資訊網(wǎng)——每日最新資訊28at.com

clearInterval(intervalId);

這會停止間隔,并允許其回調(diào)中引用的任何對象有資格進(jìn)行垃圾回收,前提是沒有其他揮之不去的引用。ge628資訊網(wǎng)——每日最新資訊28at.com

3、閉包

在JavaScript中,函數(shù)具有“記憶”它們創(chuàng)建時(shí)的環(huán)境的特殊能力。這種能力使內(nèi)部函數(shù)可以訪問外部(封閉)函數(shù)的變量,即使外部函數(shù)已經(jīng)完成其執(zhí)行。這種現(xiàn)象被稱為“閉包”。ge628資訊網(wǎng)——每日最新資訊28at.com

原因:閉包的能力伴隨著責(zé)任。閉包保持對其外部環(huán)境變量的引用,這意味著如果閉包仍然活著(例如作為回調(diào)或在事件監(jiān)聽器中),它引用的變量將不會被垃圾回收,即使外部函數(shù)早已完成其執(zhí)行。 示例:ge628資訊網(wǎng)——每日最新資訊28at.com

假設(shè)你有一個創(chuàng)建倒計(jì)時(shí)的函數(shù):ge628資訊網(wǎng)——每日最新資訊28at.com

function createCountdown(start) {  let count = start;  return function() {    return count--;  };}let countdownFrom10 = createCountdown(10);

這里,countdownFrom10 是一個閉包。每次調(diào)用它時(shí),它會將 count 變量減少一個。由于內(nèi)部函數(shù)保持對 count 的引用,count 變量不會被垃圾回收,即使在程序的其他地方?jīng)]有對createCountdown函數(shù)的其他引用。ge628資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在想象一下,如果count是一個更大、更消耗內(nèi)存的對象,閉包無意中將其保留在內(nèi)存中。ge628資訊網(wǎng)——每日最新資訊28at.com

避免方法:雖然閉包是一個強(qiáng)大的特性并且經(jīng)常是必要的,但重要的是要注意它們引用的內(nèi)容。確保你:ge628資訊網(wǎng)——每日最新資訊28at.com

  • 只捕獲你需要的內(nèi)容:除非必要,不要在閉包中捕獲大對象或數(shù)據(jù)結(jié)構(gòu)。
  • 完成后斷開引用:如果一個閉包被用作事件監(jiān)聽器或回調(diào),你不再需要它,就刪除監(jiān)聽器或使回調(diào)為null,以斷開閉包的引用。

修改上面的示例以有意斷開引用:ge628資訊網(wǎng)——每日最新資訊28at.com

function createCountdown(start) {  let count = start;  return function() {    return count--;  };}let countdownFrom10 = createCountdown(10);countdownFrom10 = null;

4、事件監(jiān)聽器

JavaScript中的事件監(jiān)聽器通過允許我們“監(jiān)聽”特定的事件(如點(diǎn)擊或按鍵)并在這些事件發(fā)生時(shí)采取行動,實(shí)現(xiàn)交互性。但與其他JavaScript功能一樣,如果不仔細(xì)管理,它們可能會成為內(nèi)存泄漏的來源。ge628資訊網(wǎng)——每日最新資訊28at.com

原因:當(dāng)你將事件監(jiān)聽器附加到DOM元素時(shí),它在該函數(shù)(通常是閉包)和該元素之間創(chuàng)建了一個綁定。如果刪除了元素或不再需要該事件監(jiān)聽器,但沒有明確刪除監(jiān)聽器,關(guān)聯(lián)的函數(shù)仍留在內(nèi)存中,可能保留其引用的其他變量和元素。ge628資訊網(wǎng)——每日最新資訊28at.com

示例:ge628資訊網(wǎng)——每日最新資訊28at.com

假設(shè)你有一個按鈕,你將一個點(diǎn)擊監(jiān)聽器附加到它:ge628資訊網(wǎng)——每日最新資訊28at.com

const button = document.getElementById('myButton');button.addEventListener('click', function() {  console.log('Button was clicked!');});

現(xiàn)在,稍后在你的應(yīng)用程序中,你決定從DOM中刪除按鈕:ge628資訊網(wǎng)——每日最新資訊28at.com

button.remove();

即使按鈕從DOM中刪除,事件監(jiān)聽器的函數(shù)仍然保留對按鈕的引用。這意味著按鈕不會被垃圾回收,導(dǎo)致內(nèi)存泄漏。ge628資訊網(wǎng)——每日最新資訊28at.com

避免方法:關(guān)鍵是積極管理你的事件監(jiān)聽器:ge628資訊網(wǎng)——每日最新資訊28at.com

明確刪除:在刪除元素或不再需要它們時(shí),使用removeEventListener()始終刪除事件監(jiān)聽器。ge628資訊網(wǎng)——每日最新資訊28at.com

使用一次:如果你知道一個事件只需要一次,你可以在添加監(jiān)聽器時(shí)使用{ once: true }選項(xiàng)。 修改上面的示例以進(jìn)行正確管理:ge628資訊網(wǎng)——每日最新資訊28at.com

const button = document.getElementById('myButton');function handleClick() {  console.log('Button was clicked!');}button.addEventListener('click', handleClick);// 稍后在代碼中,當(dāng)我們完成按鈕時(shí):button.removeEventListener('click', handleClick);button.remove();

通過在刪除按鈕之前明確地刪除事件監(jiān)聽器,我們確保監(jiān)聽器的函數(shù)和按鈕本身都可以被垃圾回收。ge628資訊網(wǎng)——每日最新資訊28at.com

5、分離的DOM元素

文檔對象模型(DOM)是網(wǎng)頁上所有元素的分層表示。當(dāng)你修改DOM,例如通過刪除元素,但仍然在JavaScript中持有對該元素的引用,你就已經(jīng)創(chuàng)建了所謂的** “分離的DOM元素” **。這些元素不再可見,但由于它們?nèi)匀槐淮a引用,所以它們不能被垃圾回收。ge628資訊網(wǎng)——每日最新資訊28at.com

原因:當(dāng)從DOM中刪除元素但仍有指向它們的JavaScript引用時(shí),會創(chuàng)建分離的DOM元素。這些引用阻止垃圾回收器回收這些元素占用的內(nèi)存。ge628資訊網(wǎng)——每日最新資訊28at.com

示例:ge628資訊網(wǎng)——每日最新資訊28at.com

假設(shè)你有一個物品列表,并且決定刪除一個:ge628資訊網(wǎng)——每日最新資訊28at.com

let listItem = document.getElementById('itemToRemove');listItem.remove();

現(xiàn)在,即使您已經(jīng)從DOM中刪除了 listItem,你仍然在 listItem 變量中對其有引用。這意味著實(shí)際的元素仍然在內(nèi)存中,從DOM中分離但占用空間。ge628資訊網(wǎng)——每日最新資訊28at.com

避免方法:為了防止分離的DOM元素引起的內(nèi)存泄漏:ge628資訊網(wǎng)——每日最新資訊28at.com

使引用為 null:刪除DOM元素后,使對其的任何引用為 null:ge628資訊網(wǎng)——每日最新資訊28at.com

listItem.remove();listItem = null;

限制元素引用:只在絕對需要時(shí)存儲對DOM元素的引用。如果你只需要對元素執(zhí)行單一操作,那么你不需要保留對它的長時(shí)間引用。ge628資訊網(wǎng)——每日最新資訊28at.com

修改上面的示例以防止內(nèi)存泄漏:ge628資訊網(wǎng)——每日最新資訊28at.com

let listItem = document.getElementById('itemToRemove');listItem.remove();listItem = null;  // 斷開對分離的DOM元素的引用

通過在從DOM中刪除 listItem 后使 listItem 引用為null,我們確保垃圾回收器可以回收已刪除元素占用的內(nèi)存。ge628資訊網(wǎng)——每日最新資訊28at.com

Websockets和外部連接

Websockets 提供了一個全雙工通信通道,通過單個、長時(shí)間的連接。這使它非常適合實(shí)時(shí)應(yīng)用,如聊天應(yīng)用、在線游戲和實(shí)時(shí)體育更新。然而,由于 Websockets 的性質(zhì)是保持開放的,如果不正確處理,它們可能成為內(nèi)存泄漏的潛在來源。ge628資訊網(wǎng)——每日最新資訊28at.com

原因:當(dāng) Websockets和其他持久的外部連接管理不當(dāng)時(shí),它們即使不再需要也可以持有對象或回調(diào)的引用。這可以阻止這些引用的對象被垃圾回收,導(dǎo)致內(nèi)存泄漏。ge628資訊網(wǎng)——每日最新資訊28at.com

示例:ge628資訊網(wǎng)——每日最新資訊28at.com

假設(shè)你有一個應(yīng)用程序,該應(yīng)用程序打開一個 websocket 連接以接收實(shí)時(shí)更新:ge628資訊網(wǎng)——每日最新資訊28at.com

let socket = new WebSocket('ws://example.com/updates');socket.onmessage = function(event) {  console.log(`Received update: ${event.data}`);};

現(xiàn)在,如果在某個時(shí)候,您導(dǎo)航離開了應(yīng)用的這一部分或關(guān)閉了使用此連接的特定UI組件,但忘記關(guān)閉 websocket,它仍然保持打開狀態(tài)。與其事件監(jiān)聽器關(guān)聯(lián)的任何對象或閉包都不能被垃圾回收。ge628資訊網(wǎng)——每日最新資訊28at.com

避免方法:積極管理websocket連接至關(guān)重要:ge628資訊網(wǎng)——每日最新資訊28at.com

明確關(guān)閉:當(dāng)不再需要時(shí),始終使用 close() 方法關(guān)閉 websocket 連接:ge628資訊網(wǎng)——每日最新資訊28at.com

socket.close();

引用為 null:關(guān)閉 websocket 連接后,使任何關(guān)聯(lián)的引用為 null 以幫助垃圾回收器:ge628資訊網(wǎng)——每日最新資訊28at.com

socket.onmessage = null;socket = null;

錯誤處理:實(shí)施錯誤處理以檢測連接何時(shí)丟失或意外終止,然后清理任何相關(guān)的資源。ge628資訊網(wǎng)——每日最新資訊28at.com

繼續(xù)上面的示例,正確的管理看起來是這樣的:ge628資訊網(wǎng)——每日最新資訊28at.com

let socket = new WebSocket('ws://example.com/updates');socket.onmessage = function(event) {  console.log(`Received update: ${event.data}`);};// 稍后在代碼中,當(dāng)連接不再需要時(shí):socket.close();socket.onmessage = null;socket = null;

工具來對抗內(nèi)存泄漏

預(yù)防內(nèi)存泄漏的最佳方法是盡早檢測它們。瀏覽器開發(fā)者工具,尤其是Chrome DevTools,可以成為你的最佳朋友。 “Memory”標(biāo)簽尤其有用,允許您監(jiān)視內(nèi)存使用情況,拍攝快照并隨著時(shí)間的推移跟蹤更改。ge628資訊網(wǎng)——每日最新資訊28at.com

總體建議

  • 定期審核:定期審查您的代碼以確保遵循最佳實(shí)踐。
  • 測試:添加新功能后,測試潛在的內(nèi)存泄漏。
  • 代碼衛(wèi)生:保持代碼整潔、模塊化并且記錄完善。
  • 第三方庫:明智地使用它們。有時(shí)它們可能是內(nèi)存泄漏的原因。

請記住,就像在現(xiàn)實(shí)生活中一樣,預(yù)防勝于治療。通過保持警覺和積極主動,你可以確保JavaScript應(yīng)用程序順暢運(yùn)行,而不會被內(nèi)存泄漏拖累。ge628資訊網(wǎng)——每日最新資訊28at.com

ge628資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-14584-0.html你的 JavaScript 正在泄漏內(nèi)存而你卻不知道

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 掌握這些套路,你也能順利解決并發(fā)問題

下一篇: 揭示Lombok的代碼設(shè)計(jì)缺陷:探索封裝問題

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 6月安卓手機(jī)好評榜:魅族20 Pro蟬聯(lián)冠軍

    性能榜和性價(jià)比榜之后,我們來看最后的安卓手機(jī)好評榜,數(shù)據(jù)來源安兔兔評測,收集時(shí)間2023年6月1日至6月30日,僅限國內(nèi)市場。第一名:魅族20 Pro好評率:95%5月份的時(shí)候魅族20 Pro就是
  • JavaScript 混淆及反混淆代碼工具

    介紹在我們開始學(xué)習(xí)反混淆之前,我們首先要了解一下代碼混淆。如果不了解代碼是如何混淆的,我們可能無法成功對代碼進(jìn)行反混淆,尤其是使用自定義混淆器對其進(jìn)行混淆時(shí)。什么是混
  • 自動化在DevOps中的力量:簡化軟件開發(fā)和交付

    自動化在DevOps中扮演著重要角色,它提升了DevOps的效能。通過自動化工具和方法,DevOps團(tuán)隊(duì)可以實(shí)現(xiàn)以下目標(biāo):消除手動和重復(fù)性任務(wù)。簡化流程。在整個軟件開發(fā)生命周期中實(shí)現(xiàn)更
  • 三分鐘白話RocketMQ系列—— 如何發(fā)送消息

    我們知道RocketMQ主要分為消息 生產(chǎn)、存儲(消息堆積)、消費(fèi) 三大塊領(lǐng)域。那接下來,我們白話一下,RocketMQ是如何發(fā)送消息的,揭秘消息生產(chǎn)全過程。注意,如果白話中不小心提到相關(guān)代
  • Python異步IO編程的進(jìn)程/線程通信實(shí)現(xiàn)

    這篇文章再講3種方式,同時(shí)講4中進(jìn)程間通信的方式一、 Python 中線程間通信的實(shí)現(xiàn)方式共享變量共享變量是多個線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • 騰訊VS網(wǎng)易,最卷游戲暑期檔,誰能笑到最后?

    作者:無銹缽來源:財(cái)經(jīng)無忌7月16日晚,上海1862時(shí)尚藝術(shù)中心。伴隨著幻象的精準(zhǔn)命中,碩大的熒幕之上,比分被定格在了14:12,被寄予厚望的EDG戰(zhàn)隊(duì)以絕對的優(yōu)勢戰(zhàn)勝了BLG戰(zhàn)隊(duì),拿下了總決
  • 網(wǎng)紅炒股不為了賺錢,那就是耍流氓!

    來源:首席商業(yè)評論6月26日高調(diào)宣布入市,網(wǎng)絡(luò)名嘴大v胡錫進(jìn)居然進(jìn)軍了股市。在一次財(cái)經(jīng)媒體峰會上,幾個財(cái)經(jīng)圈媒體大佬就“胡錫進(jìn)炒股是否知道認(rèn)真報(bào)道”展開討論。有
  • 華為HarmonyOS 4.0將于8月4日發(fā)布 或搭載AI大模型技術(shù)

    華為宣布HarmonyOS4.0將于8月4日正式發(fā)布。此前,華為已經(jīng)針對開發(fā)者公布了HarmonyOS4.0,以便于開發(fā)者提前進(jìn)行適配,也因此被曝光出了一些新系統(tǒng)的特性
  • iQOO Neo8 Pro即將開售:到手價(jià)3099元起 安卓性能最強(qiáng)旗艦

    5月23日,iQOO如期舉行了新品發(fā)布會,全新的iQOO Neo8系列也正式與大家見面,包含iQOO Neo8和iQOO Neo8 Pro兩個版本,其中標(biāo)準(zhǔn)版搭載高通驍龍8+,而Pro版更
Top 主站蜘蛛池模板: 当涂县| 泰顺县| 屯昌县| 枝江市| 融水| 财经| 利辛县| 朝阳县| 平陆县| 息烽县| 乐都县| 孟津县| 张家港市| 陕西省| 嫩江县| 中江县| 依安县| 右玉县| 渝北区| 西吉县| 南陵县| 荆门市| 大姚县| 阿克苏市| 濮阳市| 甘孜县| 炉霍县| 九寨沟县| 改则县| 高雄市| 南皮县| 麟游县| 清涧县| 郓城县| 昌乐县| 鄂托克前旗| 景德镇市| 安吉县| 普定县| 余江县| 宜君县|