【JS】上下文与垃圾回收机制

执行上下文(作用域)

执行上下文

  • 执行上下文:决定了变量和函数能访问哪些数据,以及它们的行为
  • 上下文限制:每个上下文都有一个独立的变量对象,用于存储相关数据(递归)
  • 上下文在其所有代码都执行完毕后会被销毁
  • 全局上下文在应用程序退出前才会被销毁(关闭网页或退出浏览器)
  • 上下文之间的连接是线性的、有序的。每个上下文都可以到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索(诞生闭包)

全局上下文

  • 不同的宿主环境,全局上下文的对象可能也不同

    • 在浏览器中,全局上下文是 window 对象
  • var声明的全局变量会定义在全局对象上

    • 使用 let 和 const 的声明的全局变量不会定义在全局对象上
  • 没有声明,只有赋值的变量会定义在全局上下文中

函数上下文

  • 函数参数被认为是当前上下文中的变量

  • iffor循环判断语句,没有上下文限制(坑)

    function fn(){
        console.log(a);//undefined
        if(false){
            var a=10; 没有上下文限制,被提升了
        }
    }
    
  • 在使用循环时,会污染上下文(坑)

    • 解决:套一层作用域(立即执行函数)
    var i = 99;
    因为没有上下文限制,所以会污染
    for (var i = 0; i < 5; i++) {
        console.log(i);
    }
    console.log(i);//5
    
    实际代码相当于
    var i = 99;
    {
        var i=0;
    }
    {
        var i=1;
    }
    {
        var i=2;
    }
    {
        var i=3;
    }
    {
        var i=4;
    }
    console.log(i);//5
    
    利用立即执行函数提供函数上下文限制
    var i = 99;
    (function () {
        for (var i = 0; i < 5; i++) {
        }
    })()
    console.log(i);//99
    
  • 循环内为异步时因为没有上下文限制,所以没有对象去保存相关信息

    • 解决:在内部使用立即执行函数,施加函数上下文
    for (var i = 0; i < 5; i++) {
        setTimeout(() => {
            console.log(i);
        }, 500);
    }
    // 5 5 5 5 5 
    
    for (var i = 0; i < 5; i++) {
        立即执行函数提供函数上下文,所以有相关对象去保存信息
        (function (i) { 
            setTimeout(() => {
                console.log(i);
            }, 500);
        })(i)
    }
    // 0 1 2 3 4
    

块级上下文

  • 块级上下文是函数上下文的升级版本

  • 只有 letconst 声明的变量,才具有块级上下文

  • 识别任何{},使其拥有上下文限制

    • 在使用循环时,不会污染全局作用域
    var i = 99;
    for (let i = 0; i < 5; i++) {}
    console.log(i);//99
    

    因为块级上下文限制,不会对外产生影响

    var i = 99;
    {
        let i=0;
    }
    {
        let i=1;
    }
    {
        let i=2;
    }
    {
        let i=3;
    }
    {
        let i=4;
    }
    console.log(i);//99
    

垃圾回收

  • 思路:确定哪个变量不会再使用,然后释放它占用的内存
  • 这个过程是周期性的,每隔一定时间就会自动运行
  • 主要的标记策略:标记清理和引用计数(淘汰)

标记清理

  • 当变量进入上下文,会被加上存在于上下文中的标记
  • 当变量离开上下文时,会被加上离开上下文的标记

引用计数

  • 声明变量并给它赋一个引用值时,这个值的引用数为 1
  • 如果同一个值又被赋给另一个变量,那么引用数加 1
  • 如果保存对该值引用的变量被其他值给覆盖了,那么引用数减 1
  • 当一个值的引用数为 0 时,就说明没办法再访问到这个值了,因此可以安全地收回其内存了
  • 严重的问题:循环引用
    • 两个变量相互引用,它们的引用数永远不会变成 0

内存优化

  • 保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为 null ,因为相关的值已经不在上下文里了,在下次垃圾回收时会被回收。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值