闭包作用域练习题(浏览器垃圾回收机制)

先看一道闭包作用域练习题(浏览器垃圾回收机制)

下面代码的输出结果

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);

解析图中的执行上下文都会进栈执行,但是为了简便此处省略了执行环境栈,但是执行上下文依然会进栈执行。
解析图如下:
在这里插入图片描述

  1. 先开辟一个全局执行上下文EC(G),再EC(G)中有一个存储全局变量的对象VO(G).
  2. 代码开始执行,先创建一个值5放进栈内,再创建一个变量名x,最后将两者关联起来。
  3. 先创建一个函数,开辟一个堆内存空间,这个函数堆又一个16进制的地址【0X001】,这个函数的作用域[[scope]]:EC(G),作用域就是函数创建时的执行上下文;此函数有形参x;函数体内的代码以字符串的形式保存在函数堆内。将这个堆内存地址0X001放在栈内存,创建一个函数名fn,最后将两者关联起来。
  4. 【let f = fn(6);】函数fn执行,开辟一个全新的私有的栈内存EC(FN1),这个栈内存进栈执行,返回一个小函数的堆内存0x101,将这个堆内存地址放进栈内存,创建一个变量名f,最后两者关联。
  5. 全新的私有的栈内存EC(FN1)不被释放,形成闭包,将自己私有的变量保护和保存起来。
  6. 【f(7);】函数f执行,形成一个新的执行上下文EC(F1),进栈执行后因为EC(F1)内没有被外界占有的内容,所以执行完后出栈释放。【f(10);】执行同上,也是开辟一个全新的执行上下文。
  7. 【fn(8)(9);】先执行大函数【fn(8)】,开辟一个全新的栈内存,这个外层函数暂时不会被释放,因为它的返回值也是一个函数,此内层函数接着执行【fn(8)】(9),内存函数执行也会开辟一个新的栈内存,进栈执行后出栈释放,外层函数接着也出栈释放。
    如果想把栈内存EC(FN1)释放掉,需要手动设置f=null,解除变量名f对栈内存EC(FN1)内的堆内存0x101的占用,此栈内存EC(FN1)内的内容没有被外界占有了,就会出栈释放掉。
    fn = null.释放0x001
    f= null. 释放0x101 -> EC(FN1)也会被释放
从此道题引申出垃圾回收机制:

GC:浏览器的垃圾回收机制「内存管理」
谷歌- ->查找引用
浏览器的渲染引|擎会在空闲的时候(定期一个时间),依次遍历所有的内存:栈/堆
堆:当前堆内存如果被占用(指针关联地址),则不能释放,如果没有任何的事物占用这个堆,则浏览器会自动把这个堆内存释放掉;
栈:当前上下文中是否有内容(一般是堆内存)被上下文以外的事物所占用,如果被占用则无法释放「闭包」,如果没有被占用则释放掉; -> EC(G)是在加载页面的时候创建,只有关闭页面的时候才会被释放;
IE ->引用计数
每一个内存中都有-个数字N,记录被占用的次数
如果当前内存被占用一次,则内存中的N会累加一次,反之取消占用,N会累减;知道N为0,则释放内存;
下面的方案经常导致内存泄漏思考题: 回去后总结内存泄漏的出现情况「高程三最后章节」
把占用的事物手动赋值为null (其余的值也可以,但是null更好「null不占空间的」),可以实现内存的手动优化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值