zoukankan      html  css  js  c++  java
  • js的执行上下文

    js的运行环境有三种:

    1. 全局环境
    2. 函数内环境
    3. eval环境

    1. EC

    Execute Context:  执行上下文。

        1)全局执行上下文

            js引擎遇到可执行的js代码,默认创建一个全局执行上下文。

        2)函数执行上下文

           js引擎遇到函数调用,会立即创建一个函数执行上下文。

    执行上下文周期:

    执行上下文周期分为两个阶段:

    • 创建阶段

    创建阶段的任务有三个:

    1. 生成变量对象(VO)

    2. 建立作用域链Scope

    3. 声明this指向

       this在创建阶段只是声明,在执行阶段根据函数运行时所在的执行上下文确定this指向的上下文的变量对象VO。

    • 执行阶段

    当函数执行内部代码时,进入执行阶段。

    2. VO / AO / GO

    Variable Object: 变量对象,创建阶段的变量对象。

    Active Object: 激活后的变量对象,即执行上下文执行阶段的VO。

    Global Object: 全局对象,全局执行上下文对应的变量对象(AO/VO)。

    每个执行上下文对象都有一个变量对象的属性,它用于存放执行上下文周期的创建阶段的形式参数、函数声明和变量声明。不能被用户直接访问。

    在执行上下文周期的执行阶段,VO中对应的属性被赋值,变为AO,AO中内容是变量查找的内容。

    变量对象的创建顺序如下:

    • 1. 创建arguments对象,初始化形式参数
        function a(x,y) {
          console.log(x);
        }
        a(1); // 1
        /*
        aContext: {
          AO: {
            x:1
          }
        }
        */
    • 2.查找函数声明(非函数表达式)

    遍历函数声明,将其函数名称作为AO的属性,它会覆盖同名的属性。

        function a(x,y) {
          function x() { }
          console.log(x);
        }
        a(1); // function x(){}
        /*
        aContext: {
         AO: {
            x: pointer to function x
          }
        }
        */
    • 3.查找变量声明

    查找遍历声明内容,将其变量名作为AO的属性。

    1. 如果AO中已经有同名的属性,则该变量声明忽略。

        function a(x,y) {
          function x() { }
          var x;
          console.log(x);
        }
        a(1); // function x(){}
        /*
        aContext: {
         AO: {
            x: pointer to function x
          }
        }
        */

    2. 如果有同名属性,但是如果查询阶段赋值,会覆盖前面同名属性和对应的值。

        function a(x,y) {
          function x() { }
          var x=2;
          console.log(x);
        }
        a(1); // 2
        /*
        aContext: {
          AO: {
            x: 2
          }
        }
        */

    3. 如果AO中已经后同名的形式参数,变量声明也会被忽略。

        function a(x,y) {
          var x;
          console.log(x)
        }
        a(1);  // 1
        /*
        aContext: {
          AO: {
            x: 1
          }
        }
        */

    3. 作用域链Scope

        function a() {
          function b() {
            function c() {
            }
          }
        }
    函数声明时就会产生一个作用域,位于函数的[[Scope]]属性上,指向其所有的父执行上下文的变量对象VO。
        a[[Scope]] = [// 父作用域
          globalContext.VO
        ]
        b[[Scope]] = [
          aContext.VO,
          globalContext.VO
        ]
        c[[Scope]] = [
          bContext.VO,
          aContext.VO,
          globalContext.VO
        ]

    而执行上下文的Scope属性,指向当前作用的完整的作用域链。即函数的[[Scope]]属性加上当前作用域的AO对象。

    // 例如:
    cContext = {
        AO:{
           arguments: {
               length: 0
           },
        },
        Scope: [AO, ..c[[Scope]]]
    }

    代码执行后,查找变量会根据执行上下文的作用域链开始查找,即从当前函数执行上下文的AO对象开始查找,查找不到则到上层的变量对象查找,依次查找,直到查找到全局执行上下文的变量对象为止。

    4. ECS

    Execute Context Stack: 执行上下文栈,也称为函数调用栈。

    用于存储管理所有的执行上下文对象。

    示例:

        function foo(i) {  
            if(i  == 3) {  
                return;  
            }  
            foo(i+1);  
            console.log(i);  
        }  
        foo(0);
    // 运行结果
    2
    1
    0

    js引擎遇到可执行代码,默认生成全局上下文。即位于栈底。

    ECS = [globalContext];

    遇到函数调用,将函数入栈。

    ECS.push(foo0Context);
    ECS.push(foo1Context);
    ECS.push(foo2Context);
    ECS.push(foo3Context);

    其栈结构如下:

        |------------------|
        |foo(3);console(2);|
        |------------------|
        |foo(2);console(1);|
        |------------------|
        |foo(1);console(0);|
        |------------------|
       |foo(0); |
       |------------------|
    |globalContext |
    |------------------|

    函数执行完成后,一一出栈。最后的全局上下文在浏览器关闭的时候才会销毁。

    ECS.pop();         

            

  • 相关阅读:
    awk
    Python自动化开发之python的常用模块
    sed
    python自动化开发-8
    正则表达式-2-正则表达式实战1
    linux之sort和uniq
    SSH免密登录
    Docker下安装Mongodb
    Docker下安装Elasticsearch
    Docker下安装RabbitMQ
  • 原文地址:https://www.cnblogs.com/lyraLee/p/12164474.html
Copyright © 2011-2022 走看看