自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官最愛問的 JS 內(nèi)存泄漏問題!你中招了嗎?

開發(fā) 前端
說起內(nèi)存管理,可能是很多同學(xué)既熟悉、又陌生的一個(gè)領(lǐng)域。熟悉是因?yàn)槲覀兘?jīng)常會(huì)聽到這個(gè)詞,陌生是因?yàn)楹孟裎覀冊陂_發(fā)時(shí)又很少去關(guān)注它。

Hello,大家好,我是 Sunday。

說起內(nèi)存管理,可能是很多同學(xué)既熟悉、又陌生的一個(gè)領(lǐng)域。熟悉是因?yàn)槲覀兘?jīng)常會(huì)聽到這個(gè)詞,陌生是因?yàn)楹孟裎覀冊陂_發(fā)時(shí)又很少去關(guān)注它。

不過,在目前的前端面試中,內(nèi)存管理的問題被問的又比較頻繁。所以,咱們今天就來看看 JS 內(nèi)存管理的那些事...

JavaScript 如何管理內(nèi)存

JavaScript 與許多現(xiàn)代編程語言一樣,使用自動(dòng)內(nèi)存管理,即:JS 會(huì)自動(dòng)完成垃圾回收。這也意味著,我們在程序運(yùn)行時(shí)無需手動(dòng)分配和釋放內(nèi)存(這也是很多同學(xué)很少關(guān)注它的原因)。

自動(dòng)內(nèi)存管理(垃圾回收)主要通過 標(biāo)記-清除 法完成,大致分為兩個(gè)階段:

  1. 標(biāo)記階段:垃圾收集器從根對象開始,標(biāo)記所有可到達(dá)或可訪問的對象。
  2. 清除階段:任何未標(biāo)記(即可無法訪問)的對象都被視為“垃圾”,并且其內(nèi)存將被釋放。

但是,自動(dòng)的內(nèi)存管理畢竟無法解決所有場景下的內(nèi)存問題,所以在某些特殊情況下就會(huì)導(dǎo)致出現(xiàn) 內(nèi)存泄漏 的問題。

而這個(gè) 內(nèi)存泄漏 就是我們在面試中聊到內(nèi)存管理時(shí)的,重點(diǎn)描述 內(nèi)容!

關(guān)于【內(nèi)存泄漏】

垃圾回收經(jīng)常會(huì)伴隨著內(nèi)存泄漏的概念。不過我們需要知道的是 內(nèi)存泄漏內(nèi)存溢出 是不同的。


PS 內(nèi)存溢出指的是:程序運(yùn)行過程中需要使用的內(nèi)存大于系統(tǒng)能夠提供的內(nèi)存。即:系統(tǒng)內(nèi)存不足。

所謂的內(nèi)存泄漏指的是:當(dāng)一塊內(nèi)存(通常是變量)未被釋放(垃圾回收),同時(shí)我們也無法訪問到它時(shí)。大家可以簡單理解為:一個(gè)變量,我們訪問不到它了,但是它占用的內(nèi)容還沒有被回收。那么此時(shí)就會(huì)出現(xiàn)內(nèi)存泄漏的問題:

1. 未清理的定時(shí)器或回調(diào)

  • 場景:使用 setIntervalsetTimeout,但在組件銷毀或不再需要時(shí)沒有清理。
  • 結(jié)果:定時(shí)器依然存在,引用被保留,導(dǎo)致無法釋放內(nèi)存。
  • 示例:
function startTimer() {
   setInterval(() => {
       console.log('...');
   }, 1000);
}
// 如果調(diào)用此函數(shù)后不清理定時(shí)器,則會(huì)造成內(nèi)存泄漏
  • 修復(fù):
const timer = setInterval(() => {
    console.log('Timer running...');
}, 1000);
clearInterval(timer); // 組件銷毀時(shí)清理

2. DOM 引用未釋放

  • 場景:保留對已移除 DOM 元素的引用。
  • 結(jié)果:雖然 DOM 節(jié)點(diǎn)從頁面上被刪除,但 JavaScript 中仍有對它的引用,導(dǎo)致內(nèi)存泄漏。
  • 示例:
let element = document.getElementById('leak');
document.body.removeChild(element);
// 仍然引用 element,導(dǎo)致內(nèi)存無法釋放
  • 修復(fù):
element = null; // 手動(dòng)清除引用

3. 閉包中的多余引用

  • 場景:閉包內(nèi)的變量保留了對外部對象的引用,導(dǎo)致對象無法被垃圾回收。
  • 結(jié)果:長時(shí)間的引用鏈阻止了內(nèi)存的釋放。
  • 示例:
function createClosure() {
    const largeObject = new Array(1000).fill('leak');
    return function() {
        console.log(largeObject);
    };
}
const closure = createClosure();
// 即使 closure 不再使用,largeObject 依然存在
  • 修復(fù):
function createClosure() {
    let largeObject = new Array(1000).fill('leak');
    return function() {
        console.log(largeObject);
        largeObject = null; // 主動(dòng)清除引用
    };
}

4. 全局變量或未聲明變量

  • 場景:未使用 var, let, 或 const 定義變量,導(dǎo)致變量掛載在全局作用域。
  • 結(jié)果:全局變量生命周期與頁面一致,無法被垃圾回收。
  • 示例:
function leak() {
    leakedVariable = 'I am a leak'; // 隱式全局變量
}
leak();
  • 修復(fù):
function noLeak() {
    let localVariable = 'I am safe'; // 使用局部作用域變量
}

5. 事件監(jiān)聽器未清理

  • 場景:在 DOM 元素上綁定了事件監(jiān)聽器,但沒有在元素銷毀時(shí)移除。
  • 結(jié)果:監(jiān)聽器仍然存在,阻止 DOM 元素被回收。
  • 示例:
const button = document.getElementById('myButton');
button.addEventListener('click', () => console.log('點(diǎn)擊!'));
document.body.removeChild(button);
// 內(nèi)存泄漏:button 和監(jiān)聽器仍被引用
  • 修復(fù):
const button = document.getElementById('myButton');
const handler = () => console.log('點(diǎn)擊!');
button.addEventListener('click', handler);
button.removeEventListener('click', handler); // 組件銷毀時(shí)移除
document.body.removeChild(button);

6. 忘記清理 Map/Set 中的鍵或值

  • 場景:MapSet 中的鍵/值對象未手動(dòng)移除。
  • 結(jié)果:即使這些對象不再需要,也會(huì)因其被引用而無法回收。
  • 示例:
const map = new Map();
const obj = { key: 'value' };
map.set(obj, 'data');
// 即使 obj 不再使用,map 仍然引用它
  • 修復(fù):
map.delete(obj); // 手動(dòng)清理不需要的鍵

7. 閉環(huán)引用

  • 場景:兩個(gè)對象互相引用,導(dǎo)致垃圾回收無法判斷它們是否可釋放。
  • 結(jié)果:循環(huán)引用造成內(nèi)存泄漏。
  • 示例:
function CircularReference() {
    const obj1 = {};
    const obj2 = {};
    obj1.ref = obj2;
    obj2.ref = obj1;
}
  • 修復(fù):
// 如果可能,避免互相引用,或通過 WeakMap/WeakSet 管理對象
const obj1 = new WeakMap();
const obj2 = {};
obj1.set(obj2, 'value');


責(zé)任編輯:武曉燕 來源: 程序員Sunday
相關(guān)推薦

2023-09-26 00:37:38

Spring微服務(wù)框架

2025-03-18 12:00:00

閉包JavaScript前端

2024-07-10 08:10:10

2018-01-19 10:43:06

Java面試官volatile關(guān)鍵字

2021-01-07 08:12:08

自學(xué)編程學(xué)習(xí)

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2021-08-16 14:00:27

手機(jī)科技功能

2018-10-25 10:36:50

物聯(lián)網(wǎng)誤區(qū)IOT

2018-10-22 17:52:28

GitHub代碼開發(fā)者

2010-08-23 15:06:52

發(fā)問

2013-09-30 09:18:39

2015-09-16 11:53:21

2018-08-14 11:02:55

機(jī)器學(xué)習(xí)項(xiàng)目失敗

2021-03-23 10:17:45

5G手機(jī)網(wǎng)絡(luò)

2015-08-13 10:29:12

面試面試官

2021-12-25 22:31:10

MarkWord面試synchronize

2021-11-08 09:18:01

CAS面試場景

2024-04-26 00:15:51

2022-11-04 08:47:52

底層算法數(shù)據(jù)

2022-04-01 17:32:00

Windows3.1元宇宙模式黑客
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號