堆內(nèi)存
對象數(shù)據(jù)類型,或者函數(shù)數(shù)據(jù)類型,在定義的時候,首先都會開辟一個堆內(nèi)存,堆內(nèi)存有一個引用地址,如果外面有變量知道了并引用這個地址,我們就說這個內(nèi)存被占用了,就不能被銷毀了。
var obj1 = {
name: 'zhangsan'
};
var obj2 = obj1;
想要堆內(nèi)存釋放/銷毀,只需要把所有引用它的變量值賦值為null即可,如果當前的堆內(nèi)存沒有任何東西被占用了,那么瀏覽器會在空閑的時候把它銷毀。
obj1 = null;
obj2 = null;

分析圖.png
棧內(nèi)存
全局作用域:只有當頁面關(guān)閉的時候,全局作用域才能被銷毀。
私有作用域(只有函數(shù)執(zhí)行會產(chǎn)生私有作用域)
一般情況下函數(shù)執(zhí)行會形成一個新的私有作用域,當私有作用域中的代碼執(zhí)行完成后,當前作用域都會進行主動的釋放和銷毀。
但是還是存在特殊的情況:當前私有作用域的部分內(nèi)容被作用域以外的東西都占用了,那么當前的這個作用域就不能被銷毀了。
a. 函數(shù)執(zhí)行返回了一個引用數(shù)據(jù)類型的值,并且在函數(shù)的外面被一個其他的東西接收了,這種情況下一般形成的私有作用域都不會被銷毀。
function fn() {
var num = 100;
return function () {
num++;
console.log(num);
}
}
var f = fn(); // fn執(zhí)行形成的這個私有作用域就不能被銷毀了
b. 在一個私有的作用域中,給DOM元素元素的事件綁定方法,一般情況下私有作用域都不銷毀。
var oDiv = document.getElementById('div1');
~function () {
oDiv.onclick = function () {
}
}(); // 當前自執(zhí)行函數(shù)形成的這個私有的作用域也不銷毀

分析圖.png
c. 下述情況屬于不立即銷毀 -> fn返回的函數(shù)沒有被其他的東西占用,但是還需要執(zhí)行一次,所以暫時不銷毀,當返回的值執(zhí)行完成后,瀏覽器會在空閑的時候?qū)⑵滗N毀,稱之為"不立即銷毀"。
function fn() {
var num = 100;
return function () {
}
}
fn()(); // 首先執(zhí)行fn,返回一個小函數(shù)對應(yīng)的內(nèi)存地址,然后緊接著讓返回的小函數(shù)再執(zhí)行
一道面試題:
function fn() {
var i = 10;
return function (n) {
console.log(n + (++i));
}
}
var f = fn();
f(10); // 21
f(20); // 32
fn()(10); // 21
fn()(20); // 31

分析圖.png
function fn(i) {
return function (n) {
console.log(n + (++i));
}
}
var f = fn(13);
f(12); // 26
f(14); // 29
fn(15)(12); // 28
fn(16)(23); // 40