JavaScript中的垃圾回收(gc)機制是指會在代碼執行過程中,自動識別不再被使用的內存空間,并將其釋放掉。這種機制旨在避免內存誤用,避免內存泄露等問題。
比如說,如果你在JavaScript中創建一個對象,但是后來你沒有再使用這個對象了,那么gc會自動釋放它占用的內存,沒有使用的內存被系統回收了,提高了內存空間的利用效率。如果這個對象的引用計數變成了0,那么gc就會自動回收這個對象占用的內存空間。
var obj = {
name: "John",
age: 26,
address: "xxx street"
};
obj = null; //此時obj對象不再被任何引用,gc會回收該對象占用的內存
然而,當代碼中存在內存泄露的情況時,gc就無法起到它的作用。內存泄露指的是在程序執行過程中,由于一些原因沒有及時釋放不再需要的對象,導致內存空間得不到釋放,從而產生“泄露”現象。比如:
//創建一個數組,但是后面沒有釋放該數組,導致內存空間得不到回收
var arr = [];
for(var i=0;i<1000000;i++){
arr.push(i);
}
此時內存中會有1000000個整數類型的數據,占用的內存空間是比較大的,造成了內存空間的浪費。 另外一種比較常見的內存泄露是事件監聽。如果你在函數中注冊了一個事件監聽器,但是在函數執行完后沒有移除該事件監聽器,那么這個監聽器就不會被gc回收。
var button = document.getElementById('button');
button.addEventListener('click', function(){
//....
});
//在不使用該監聽器的時候,需要手動移除
button.removeEventListener('click', function(){
//....
});
還有一種特殊情況是,一個對象的屬性被另一個對象引用,那么無論這兩個對象被引用計數為多少,這個屬性所占用的內存空間不會被回收。比如:
var obj1 = {
a: {
b: 1
}
};
var obj2 = obj1.a;
obj1 = null;
obj2 = null;
//此時上面的例子會產生內存泄露,因為obj1.a的內存空間得不到回收
這個例子中,雖然obj1和obj2的引用計數變為了0,但是obj1.a的引用計數不為0,所以它的內存空間得不到釋放。 針對內存泄露的問題,我們可以手動釋放不再需要的內存。比如移除事件監聽器、刪除不再需要的變量等等。在編碼的時候,盡量少使用全局變量也是一個很好的編碼習慣,可以避免出現某些對象得不到釋放的問題。
總之,內存泄露是一種不能被gc回收的內存空間占用,而gc機制是一種自動減輕內存泄露的技術手段,我們需要在編碼中注意避免內存泄露,避免內存浪費。當我們的代碼出現了內存泄露時,心平氣和地學會排查和解決問題也是很重要的。