成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:講一下閉包?內存泄露場景?循環引用為什么導致內存泄露?怎么判斷是否存在循環引用?

開發 前端
這篇文章就跟大家詳細的說一下關于閉包的問題,爭取可以做到讓大家看完這篇文章之后,對比閉包的問題可以順暢回答!

Hello,大家好,我是 Sunday。

在最近的中小廠面試中,【閉包】的問題被很多公司提到。如果單純說閉包是比較簡單的,一句話就可以說清楚:“可以訪問其他函數作用域中變量的函數,就是閉包函數”。

但是,隨后延伸的問題,如:閉包造成內存泄漏的場景、循環引用為什么導致內存泄露?怎么判斷是否存在循環引用? 等問題,很多同學回答的并不好。

因此,這篇文章就跟大家詳細的說一下關于閉包的問題,爭取可以做到讓大家看完這篇文章之后,對比閉包的問題可以順暢回答!

1. 什么是閉包

閉包是指 函數在創建時保留了對其定義作用域的引用,即使函數執行在其詞法作用域之外,也能訪問該作用域中的變量。

閉包在 JavaScript 中的常見表現形式是:函數嵌套函數,內部函數訪問外部函數的變量。

由于 JavaScript 的函數是“第一類公民”,可以作為值返回、傳遞或保存,因此在外部函數返回后,閉包依然保留對外部變量的訪問權限。

function outerFunction() {
  let counter = 0;
  
  return function innerFunction() {
    counter++;
    console.log(counter);
  };
}

const increment = outerFunction();
increment(); // 輸出: 1
increment(); // 輸出: 2

在上述代碼中,innerFunction 是一個閉包,它可以訪問 outerFunction 中的變量 counter,即使 outerFunction 已經執行完畢。

2. 閉包導致的內存泄露場景

在 JS 中,閉包有時會導致內存泄露,這是因為:閉包在訪問外部作用域的變量時會讓這些變量無法被垃圾回收,從而導致不必要的內存占用。

2.1. 常見的內存泄露場景

  • 未清理的事件監聽:如果事件監聽器引用了外部作用域中的變量,且在不需要時未移除,則會導致閉包一直存在,無法釋放內存。
function addEvent() {
  const element = document.getElementById('button');
  const someData = "Important data";
  element.addEventListener('click', function() {
    console.log(someData); // 閉包引用了外部變量 someData
  });
}

addEvent();
// 這里如果不手動移除事件監聽器,則 someData 永遠不會被釋放,造成內存泄露
  • 定時器未清理:在定時器的回調函數中使用了閉包,但在不再需要時未清除定時器,導致回調函數及其引用的外部變量無法被回收。
function createTimer() {
  const largeData = new Array(10000).fill('*');
  setInterval(function() {
    console.log(largeData); // 定時器閉包持有 largeData 的引用
  }, 1000);
}

createTimer();
// 這里如果不清除定時器,largeData 將永遠無法釋放

3. 循環引用導致內存泄露

循環引用是指:兩個或多個對象相互引用,從而形成一個循環結構,導致垃圾回收器無法回收這些對象。

3.1. 為什么循環引用會導致內存泄露?

JS 的垃圾回收機制使用 標記清除(mark-and-sweep) 算法。即:垃圾回收器會從根對象(如全局對象)出發,查找所有可達對象。

若對象形成了循環引用,且不再被根對象訪問,則垃圾回收器無法將其清除,這會導致這些對象長期保留在內存中,形成內存泄露。

function createCircularReference() {
  const objectA = {};
  const objectB = {};
  objectA.ref = objectB; // objectA 引用 objectB
  objectB.ref = objectA; // objectB 引用 objectA,形成循環引用
}

createCircularReference();
// 這里 objectA 和 objectB 都無法被回收

在這個示例中,objectA 和 objectB 互相引用,形成了循環引用。如果沒有外部引用它們,按理說可以被垃圾回收,但由于相互持有的引用,導致它們無法被清除,形成內存泄露。

4. 如何檢測循環引用

在項目中,如果出現 內存泄漏 的問題,那么可以通過以下方式進行檢查:

  • 手動檢測:在代碼中通過邏輯分析或使用 console.log 輸出檢查對象的相互引用關系。
  • 使用開發者工具檢測:現代瀏覽器的開發者工具提供了內存快照和堆分析,可以捕獲內存快照來分析內存的使用情況,幫助發現循環引用和內存泄露。在 Chrome 開發者工具中,可以通過 Memory(內存) 面板,使用 Heap Snapshot(堆快照)來查看對象的引用關系,并檢查是否有意外的循環引用。

圖片圖片

  • JSON.stringify 檢測:嘗試使用 JSON.stringify 序列化對象,如果對象中存在循環引用,JSON.stringify 會拋出 TypeError 異常,可以用這種方式簡單檢測循環引用(注意這種方法只能用于檢測較簡單的循環引用,復雜場景需結合其他方法)。
function hasCircularReference(obj) {
  try {
    JSON.stringify(obj);
    return false; // 無循環引用
  } catch (error) {
    return true; // 有循環引用
  }
}

const objectA = {};
const objectB = { ref: objectA };
objectA.ref = objectB;

console.log(hasCircularReference(objectA)); // 輸出: true
  1. WeakMap 弱引用:使用 WeakMap 結構管理對象引用。由于 WeakMap 的鍵是弱引用,不會影響對象的垃圾回收,可以通過 WeakMap 追蹤對象引用關系,并避免循環引用導致的內存泄露。

5. 如何避免循環引用導致的內存泄露

如果檢測出現內存泄漏的問題,那么可以通過以下方式嘗試解決:

  • 避免對象互相引用:在設計數據結構時,盡量避免互相引用,尤其是大的復雜對象。
  • 使用 WeakMap 或 WeakSet:在 JavaScript 中,WeakMap 和 WeakSet 是弱引用結構,存儲在 WeakMap 或 WeakSet 中的對象不會被阻止垃圾回收。可以使用 WeakMap 和 WeakSet 來存儲對象之間的引用關系,避免循環引用導致的內存泄露。
const weakMap = new WeakMap();
const objectA = {};
const objectB = {};

weakMap.set(objectA, objectB);
  • 在不需要時手動斷開引用:當對象不再使用時,可以手動將引用設為 null 或 undefined,確保垃圾回收器能夠正常回收它們。
let objectA = {};
let objectB = {};
objectA.ref = objectB;
objectB.ref = objectA;

// 當不再需要時,斷開引用關系
objectA.ref = null;
objectB.ref = null;


責任編輯:武曉燕 來源: 程序員Sunday
相關推薦

2025-05-22 09:35:24

2017-11-15 19:30:08

Python內存泄露循環引用

2017-12-11 11:00:27

內存泄露判斷

2016-09-08 16:16:26

iOS移動應用內存泄漏

2022-06-07 12:03:33

Java內存模型

2021-12-20 10:30:33

forforEach前端

2021-10-27 07:15:36

Go 循環引用

2022-10-18 08:38:16

內存泄漏線程

2024-03-13 07:53:57

弱引用線程工具

2024-02-22 15:36:23

Java內存模型線程

2020-08-07 15:15:01

Java內存泄漏面試

2025-03-10 07:05:07

2021-05-27 21:47:12

Python垃圾回收

2025-02-27 00:08:24

2023-09-12 14:56:13

MyBatis緩存機制

2021-04-19 18:56:58

大數字符串運算

2017-05-04 16:07:11

Tomcat內存泄露

2013-08-07 10:07:07

Handler內存泄露

2022-10-10 11:37:14

Gomap內存

2021-07-28 10:08:19

類加載代碼塊面試
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲性人人天天夜夜摸 | 午夜免费福利影院 | 日韩国产高清在线观看 | 日韩在线观看网站 | 中文字幕一区二区三区四区五区 | 国产精品18hdxxxⅹ在线 | 欧美一区二区在线观看视频 | 免费观看黄 | 国产精品美女久久久免费 | 视频一区二区在线观看 | 精品欧美一区二区三区久久久 | 久草网站 | 日韩精品一区二区三区在线 | 国产一区二区三区四区五区3d | 精品视频久久久久久 | 欧美精品在线免费 | 97精品超碰一区二区三区 | 久久噜噜噜精品国产亚洲综合 | 九九热这里只有精品在线观看 | 欧美日韩久 | 亚洲精品久久久蜜桃网站 | 免费观看一级黄色录像 | 中文字幕 在线观看 | 成人一区二区电影 | 国产精品一区二区三区久久久 | 人人草人人干 | 日韩视频在线观看一区二区 | 成人一区在线观看 | 成人在线视频一区 | 久久久久久免费免费 | 精品国产欧美一区二区 | 免费观看一级视频 | 国产毛片久久久久久久久春天 | 欧美一区二区三区的 | 欧美激情国产日韩精品一区18 | 国产精品久久久久久久三级 | 国产高清一区二区三区 | 国产成人精品999在线观看 | 亚洲一区二区久久 | 中文福利视频 | 美日韩精品 |