最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 理解执行上下文和其生命周期

    正文概述 掘金(颜酱)   2021-01-21   619

    代码一旦变多,我们就会尝试写函数、拆文件、拆模块,从而让代码更容易。

    将庞大的问题拆分成一个个小问题的思想,叫分治(突然想到皇帝的政策)。

    同理,JS 引擎在执行阶段,会将把庞大的执行任务划分成不同的执行上下文,降低执行的复杂度。

    执行上下文是啥

    执行上下文,简言之,“执行代码的环境”。结合分类、生命周期更易懂些。

    执行上下文分为 3 类:

    • 全局上下文 —— 全局代码所处的环境,不在函数中的代码都在全局执行上下文中
    • 函数上下文 —— 在函数调用时创建的上下文
    • eval上下文 —— 笔者不用eval,读者也别用,问就是没用过~

    执行上下文的生命周期:

    • 创建阶段 —— 执行上下文的初始化状态,此时一行代码都还没有执行,只是做了一些准备工作(进栈)
    • 执行阶段 —— 逐行执行脚本里的代码
    • 消失阶段 -- 出栈

    全局上下文的生命周期

    JS 脚本运行起来之后,会第一时间创建全局上下文

    全局上下文创建阶段做的事情:

    • 创建全局对象(Window/Global)
    • 创建 this ,并让它指向全局对象
    • 给变量和函数安排内存空间,默认给变量赋值为 undefined;将函数声明放入内存
    • 创建作用域链

    执行阶段就开始执行代码。

    而之前所谓的变量提升,只是变量的创建过程(在上下文创建阶段完成)和真实赋值过程(在上下文执行阶段完成)的不同步带来的一种错觉。

    函数上下文的生命周期

    和全局上下文大同小异。

    函数上下文在函数调用的时候就会被创建。

    • 创建 arguments
    • 创建 this ,并让它指向调用对象
    • 给变量和函数安排内存空间,默认给变量赋值为 undefined;将函数声明放入内存
    • 初始化作用域链

    执行阶段就开始执行代码。 执行完毕,就出栈了。

    上面说到了初始化作用域链,怎么初始化?

    执行上下文栈

    JS 引擎在执行过程中,会为我们自动创建” 执行上下文栈 “(也叫调用栈)。

    全局上下文执行栈始终在最底层。

    调用函数的时候,函数上下文就会进栈,执行完就会出栈,也就是该上下文就结束了。

    作用域链的生命周期

    参考大神写的深入作用域链 作用域链的生命周期:

    • 全局上下文创建阶段,声明函数的时候,就保存了根据词法所生成的作用域链
    • 函数调用之后,函数上下文被创建(进栈)
    • 函数上下文在创建阶段,会复制这个作用域链,作为自己作用域链的初始化,然后根据环境生成变量对象,将这个变量对象,添加到这个复制的作用域链
    • 函数上下文在执行阶段,会将当前作用域链的相关值更新
    • 函数执行完,函数上下文出栈,刚刚复制的作用域链失效

    至于为什么会有两个作用域链,是因为在函数创建的时候并不能确定最终的作用域的样子,为什么会采用复制的方式而不是直接修改呢?应该是因为函数会被调用很多次吧。

    举个例子:

    var scope = "global scope";
    function checkscope() {
      var scope2 = "local scope";
      return scope2;
    }
    checkscope();
    

    全局上下文在创建阶段:

    stacks = [globalContext];
    checkscope.[[scope]] = [
        globalContext.VO
    ];
    

    执行checkscope()这行代码的时候:

    // checkscopeContext进栈
    stacks = [checkscopeContext, globalContext];
    

    checkscopeContext 在创建阶段:

    // 先复制
    checkscopeContext = {
        Scope: checkscope.[[scope]]
    }
    // 然后用 arguments 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明
    checkscopeContext = {
        AO: {
          arguments: { length: 0 },
          scope2: undefined
        },
        Scope: checkscope.[[scope]]
    }
    // 再将活动对象放在checkscope 作用域链顶端
    checkscopeContext = {
        AO: {
            arguments: { length: 0 },
            scope2: undefined
        },
        Scope: [AO, [[Scope]]]
    }
    

    checkscopeContext 在执行阶段:

    // 修改 AO 的属性值
    checkscopeContext = {
      AO: {
        arguments: { length: 0 },
        scope2: "local scope"
      },
      Scope: [AO, [[Scope]]]
    };
    

    执行完之后,checkscopeContext 出栈

    stacks = [globalContext];
    

    为啥,作用域在嵌套的情况下,外部作用域是不能访问内部作用域的变量呢?

    因为当 JS 引擎位于外部上下文的时候,表明内部上下文已经出栈了,其维护的自己的作用域链也消失了,自然访问不到其变量。

    理解闭包作用域

    闭包里,虽然父作用域在父函数执行完就出栈了,但是,因为父函数执行的时候,闭包函数本身也保存了一份父函数的作用域数据,所以当闭包函数执行的时候,仍可访问到父函数的作用域数据。

    先看这个例子,参考大神的深入闭包

    var scope = "global scope";
    function checkscope() {
      var scope = "local scope";
      function f() {
        return scope;
      }
      return f;
    }
    // checkscope执行完之后,checkscopeContext是肯定出栈的
    var foo = checkscope();
    // 那么在foo执行的时候,为什么能访问
    foo();
    

    checkscope执行完之后,checkscopeContext是肯定出栈的。

    那为什么foo执行的时候,还能访问checkscopeContext

    联系之前的作用域生命周期来理解这个问题:

    // 全局作用域在创建阶段:
    fContext.[[scope]] = [
        checkscopeContext.VO,
        globalContext.VO
    ];
    // checkscopeContext在运行阶段:
    fContext.[[scope]] = [
        // 此处保留了checkscopeContext的AO,也就是保留了其arguments/参数值/变量值/定义的函数
        checkscopeContext.AO,
        globalContext.VO
    ];
    // fContext在执行阶段:
    fContext = {
        // 优先访问自己的AO,找不到,仍然可以访问checkscopeContext.AO
        Scope: [AO, checkscopeContext.AO, globalContext.VO],
    }
    

    起源地下载网 » 理解执行上下文和其生命周期

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元