六角學院 JS 核心筆記 (八)【執行環境與作用域】- 記憶體存放與釋放

AdSense

前言

記憶體的管理,在早期是軟體工程師一個很重要很困難的課題。現代大部分高階語言中多虧了回收機制 (Garbage Collection),能讓軟體工程師的負擔稍微少了一點。

原理

當一個已經不再被使用的變數,也就是一個不再被使用的記憶體配置空間,需要被清除,並且將該記憶體空間釋放出來,重新回到可以被配置新變數的隊伍中。

但是要如何定義「一個記憶體配置空間不再被使用」呢?

最一開始是簡化成「沒有其他任何物件參考 / 指向它」,因為沒有其他物件參考它,就表示無法取用它。但是這邊有一個例外:循環參考。

1
2
3
4
5
6
7
8
9
10
function f() {
var o = {};
var o2 = {};
o.a = o2; // o 參考 o2
o2.a = o; // o2 參考 o

return 'azerty';
}

f();

當我其他的程式碼不會運用到 oo2 時,它們其實應該被清除,但是因為互相參考,因此不符合「沒有其他任何物件參考 / 指向它」這個定義。

後來這個定義被修正成「這個物件不會被尋訪到、不可到達」,一個物件不會被尋訪到,表示無法取用它,即使是循環參考,如果它們都無法被取用,則代表它們應該被清除且釋放記憶體空間。

回收機制

大部分的高階語言都有垃圾回收器 (Garbage Collector) 的機制,它就像是垃圾車一樣,會自動追蹤記憶體分配的使用情況,「盡力」去釋放那些不再使用的記憶體空間。

檢驗記憶體使用空間

Chrome 的開發者工具中,有一欄 Memory,點擊 Take heap snapshot 會顯示記憶體的使用和分佈,但是這個監測數據是有一點點延遲的狀態。

注意:Chrome console 中的行為也會需要記憶體。如果一個變數的詞法作用域是在 local scope 中,當函式執行完畢從 stack 中清除時,照理來說該變數佔用的記憶體空間也要被清除。但是如果我有用 console.log(變數); 該變數佔用的記憶體空間會仍然存在。

參考資料:
記憶體管理
六角學院:JavaScript 核心篇 - 邁向達人之路