堆内存
对象数据类型,或者函数数据类型,在定义的时候,首先都会开辟一个堆内存,堆内存有一个引用地址,如果外面有变量知道了并引用这个地址,我们就说这个内存被占用了,就不能被销毁了。
var obj1 = {
name: 'zhangsan'
};
var obj2 = obj1;
想要堆内存释放/销毁,只需要把所有引用它的变量值赋值为null即可,如果当前的堆内存没有任何东西被占用了,那么浏览器会在空闲的时候把它销毁。
obj1 = null;
obj2 = null;
栈内存
全局作用域:只有当页面关闭的时候,全局作用域才能被销毁。
私有作用域(只有函数执行会产生私有作用域)
一般情况下函数执行会形成一个新的私有作用域,当私有作用域中的代码执行完成后,当前作用域都会进行主动的释放和销毁。
但是还是存在特殊的情况:当前私有作用域的部分内容被作用域以外的东西都占用了,那么当前的这个作用域就不能被销毁了。
a. 函数执行返回了一个引用数据类型的值,并且在函数的外面被一个其他的东西接收了,这种情况下一般形成的私有作用域都不会被销毁。
function fn() {
var num = 100;
return function () {
num++;
console.log(num);
}
}
var f = fn(); // fn执行形成的这个私有作用域就不能被销毁了
b. 在一个私有的作用域中,给DOM元素元素的事件绑定方法,一般情况下私有作用域都不销毁。
var oDiv = document.getElementById('div1');
~function () {
oDiv.onclick = function () {
}
}(); // 当前自执行函数形成的这个私有的作用域也不销毁
c. 下述情况属于不立即销毁 -> fn返回的函数没有被其他的东西占用,但是还需要执行一次,所以暂时不销毁,当返回的值执行完成后,浏览器会在空闲的时候将其销毁,称之为"不立即销毁"。
function fn() {
var num = 100;
return function () {
}
}
fn()(); // 首先执行fn,返回一个小函数对应的内存地址,然后紧接着让返回的小函数再执行
一道面试题:
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
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