JS中堆栈内存的释放问题

开辟的堆内存或者造成的上下文(进栈执行=>栈内存)是越多越好,仍是越少越好?javascript

  • 确定是越少越好,由于计算机的内存是固定的,咱们全部开辟的内存都在占用计算机的资源,当计算机内消耗存过多,性能也就愈来愈卡(直接致使咱们的产品运行变慢)

思惟导图

函数执行就会造成栈内存(从内存中分配的一块空间),若是内存都不销毁释放,很容易就会致使栈内存溢出(内存爆满,电脑就卡死了), => 因此JS中一个重要的性能优化点:减小内存的使用java

  • =>释放堆内存
  • =>释放栈内存(也就是让进栈执行的上下文,尽量出栈释放)

1、堆内存(HEAP)和 栈内存(STACK)

一、堆内存(HEAP)

  • 堆内存是用来存储引用数据类型值的
    • (例如:建立函数和建立对象,就是开辟一个堆内存,把代码字符串或者键值对存储到堆内存中的)

二、栈内存(STACK)

  • 栈内存是用来执行代码和存储基本类型值的(建立的变量也存栈里面了),
    • 不只全局代码执行(EC(G)全局执行上下文),
    • 并且函数执行(EC(X)私有上下文),最后也都会进栈执行的
    • 基于ES6中的let/const造成的块做用域也是栈内存

2、浏览器经常使用的垃圾回收机制(内存释放机制):

一、 查找引用方式(weblit内核)

浏览器有自动回收垃圾的机制,按期间隔某段时间,把全部没有被占用的内存回收释放(这种垃圾回收机制,比其它语言要完善一些)web

-1).不会销毁的状况:

  • 建立一个堆(16进制地址):
    • 若是有变量或者其它东西存储了堆内存的地址,则当前堆内存被视为占用,也就不能释放销毁
  • 上下文进栈执行;
    • 若是当前上下文中的某些内容(通常也是当前上下文中建立的堆)被上下文之外的变量或者其它事务所占用,那么当前上下文就不能出栈释放(可是通常状况下,上下文中代码执行完,上下文本身就出栈释放了)

-2).堆内存释放

若是堆内存用完后,咱们想去手动释放它,则取消全部的占用:赋值为NULL(NULL是空对象指针,也就是不指向任何的堆内存)浏览器

//=>建立一个引用类型值,就会产生一个堆内存
//若是当前建立的堆内存不被其它东西所占用了(浏览器会在空闲的时候,查找每个内存的引用情况,不被占用的都会给回收释放掉),则会释放
let obj = {
    name : 'xiaozhima'
};
let oop = obj;
//此时obj和oop都占用着对象的堆内存,想要释放堆内存,须要手动解除变量和值的关联(null:空对象指针)
obj = null;
oop = null;
复制代码

-3).栈内存释放

栈内存:性能优化

  • 打开浏览器造成的全局做用域是栈内存
  • 手动执行函数造成的私有做用域是栈内存
  • 基于ES6中的let/const造成的块做用域也是栈内存
  • ......

栈内存销毁:bash

  • 全局栈内存:关掉页面的时候才会销毁
  • 私有栈内存:
    • 1.通常状况下,函数只要执行完成,造成的私有栈内存就会被销毁释放掉(排除出现无限极递归、出现死循环的模式)
    • 2.可是一旦栈内存中的某个东西(通常都是堆地址)被私有做用域之外的事物给占用了,则当前私有栈内存不能当即被释放销毁(特色:私有做用域中的私有变量等信息也保留下来了=>这种函数执行造成不能被释放的私有栈内存,也叫作闭包)
function fn(){
    //...
}
fn(); //=>函数执行造成栈内存,执行完成栈内存销毁
     
function X(){
    return function(){
        //...
    }
}
let f=X(); //=>f占用了X执行造成的栈内存中的一个东西(返回小函数对应的堆),则X执行造成的栈内存不能被释放了
复制代码

二、内存计数器方式(Trident内核)

当前内存被其它东西引用了,则给堆计数1(累加计数),取消占用后,则减1,当减到零以后,浏览器就能够把它释放了闭包

3、练习题

1.输出结果

var i = 5;
function fn(i) {
	return function (n) {
		console.log(n + (++i));
	}
}
var f = fn(1);
f(2);
fn(3)(4);
fn(5)(6);
f(7);
console.log(i);
复制代码

2.输出结果

let x = 5;
function fn(x) {
    return function(y) {
        console.log(y + (++x));
    }
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
复制代码

3.输出结果

let a=0,
    b=0;
function A(a){
    A=function(b){
        alert(a+b++);
    };
    alert(a++);
}
A(1);
A(2);
复制代码

4.输出结果

var n=0; 
function a(){
    var n=10; 
    function b(){
        n++; 
        console.log(n); 
    }
    b();
    return b; 
}
var c=a();
c(); 
console.log(n);
复制代码

5.输出结果

var test = (function(i){
    return function(){
        alert(i*=2);
    }
})(2);
test(5);
复制代码

相关文章
相关标签/搜索