1.JS中的内存:堆内存(HEAP)和栈内存(STACK)
- 堆内存是用来存储引用数据类型值的(例如:创建函数和创建对象,就是开辟一个堆内存,把代码字符串或者键值对存储到堆内存中的)
- 内存是用来执行代码和存储基本类型值的(创建的变量也存栈里面了),不仅全局代码执行(EC(G)全局执行上下文),而且函数执行(EC(X)私有上下文),最后也都会进栈执行的
2.开辟的堆内存或者形成的上下文(进栈执行=>栈内存)是越多越好,还是越少越好?
- 肯定是越少越好,因为计算机的内存是固定的,我们所有开辟的内存都在占用计算机的资源,当计算机内消耗存过多,性能也就越来越卡(直接导致我们的产品运行变慢) => 所以JS中一个重要的性能优化点:减少内存的使用
- =>释放堆内存
- =>释放栈内存(也就是让进栈执行的上下文,尽可能出栈释放)
3.浏览器常用的垃圾回收机制(内存释放机制)
浏览器有自动回收垃圾的机制,定期间隔某段时间,把所有没有被占用的内存回收释放(这种垃圾回收机制,比其它语言要完善一些)
-
1)查找引用(weblit内核)
- 创建一个堆(16进制地址),如果有变量或者其它东西存储了堆内存的地址,则当前堆内存被视为占用,也就不能释放销毁
- 上下文进栈执行,如果当前上下文中的某些内容(一般也是当前上下文中创建的堆)被上下文以外的变量或者其它事务所占用,那么当前上下文就不能出栈释放(但是一般情况下,上下文中代码执行完,上下文自己就出栈释放了)
-
2)内存计数器方式(Trident内核)
- 当前内存被其它东西引用了,则给堆计数1(累加计数),取消占用后,则减1,当减到零之后,浏览器就可以把它释放
// 此时 ARR1/2/3 都占用了这个堆内存 let arr1 = [10, 20]; let arr2 = arr1; let arr3 = arr2; // .... //如果堆内存用完后,我们想去手动释放它, //则取消所有的占用:赋值为NULL //(NULL是空对象指针,也就是不指向任何的堆内存) arr1 = null; arr2 = null; arr3 = null;
-
堆栈释放与不释放计算题
var i = 5; function fn(i) { return function (n) { console.log(n + (++i)); } } var f = fn(1); f(2);//4 fn(3)(4);//8 fn(5)(6);//12 f(7);//10 console.log(i);//5