js执行环境相关

Js执行过程

	如果一个文档中存在多个代码段 
		步骤一:读入第一个代码段(js引擎并非一行一行执行,而是一段一段分析执行)
		步骤二:做词法分析和语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤5     
		步骤三:对【var】变量和【function】定义做“预解析“(永远不会报错的,因为只解析正确的声明)
		步骤四:执行代码段 ,有错则报错(比如变量未定义)
		步骤五:如果还有下一代码段,则读入下一代码段,重复步骤二
		步骤六:结束

通过步骤二 js会先生成一个语法分析树(SyntaxTree)

语法分析树可以理解为 记录 变量集 作用域集 方法集的  数据库一样的东西。

/**
* 模拟建立一棵语法分析树,存储function内的变量和方法
*/

var  SytaxTree = {
    
        window={
           variables:{
                name:{value:'HEBO'}   //假设我们全局变量中有一个name
            },
            functions:{
                 sayName:this.sayName
            }
       },
        sayName:{
             scope:this.window,
             function:{}
     }
}

//在这一步的时候 变量集中 只有变量定义,没有变量值,这时候的变量值全部为“undefined”
//

词法作用域: 变量在定义的时候形成作用域,而不是在执行的时候。

在进入上下文时声明,在执行上下文赋值

function test(){
  
   var a =0;   //定义的时候决定了作用域
      
}

console.log(a); // a is not defined

 执行环境与活动对象

我们调用每一个方法的时候,JS 引擎都会自动为其建立一个执行环境和一个活动对象,它们和方法实例的生命周期保持一致,为方法执行提供必要的执行支持

执行环境ExecutionContext: 记录了当前方法的外部描述信息,比如类型,名称,参数和活动对象(activeObject)

var ExecutionContext = {
    window: {
        type: "global",
        name: "global",
        body: ActiveObject.window    
    },
 
    a:{              //记录了a方法的 一些执行上下文信息
        type: "function",
        name: "a",
        body: ActiveObject.a,     //指向当前方法的活动对象
        scopeChain: this.window.body    //作用域链  它指向的是 对应方法的活动对象 ,既window.body(ActiveObject.window ) 变量查找就是跟着这条链条查找的
}
};

在执行的时候才生成活动对象 ,活动对象的 北部变量集、内嵌函数集是从 语法分析树 复制过来的

活动对象ActiveObject: 记录了当前方法的内部描述信息,内部变量集(variables)、内嵌函数集(functions)、实参(arguments)、作用域链(scopeChain)等执行所需信息

var ActiveObject={
     
       window:{},
       
       a:{                       //这里的a 对应上文的 ActiveObject.a
           variables:{
                x: {value:4}
            },
            functions:{
                b: SyntaxTree.b
            },
parameters:{ //形参

        },
      arguments:[] //实参
} }

 一个方法的执行过程:

  1. 创建活动对象,从语法分析树复制方法的内部变量集(variables)和内嵌函数集(functions)
  2. 方法开始执行时: 活动对象- 内部的变量全部被重置为undefined 。
  3. 创建形参(parameters)和实参(arguments)对象,同名的实参,形参和变量之间是【引用】关系
  4. 执行方法内的赋值语句 : 内部的变量才会被赋值 。
  5.  变量查找规则: 现在当前的ActiveObject查找,找不到 则顺着 scopeChain 指向的活动对象 继续,直到找到最顶点 ActiveObject.window
  6.  方法执行完毕以后:内部变量不会被重置
  7. 方法内变量的生存周期取决于方法实例是否存在活动引用,如没有就销毁活动对象

6.7 是使闭包能够访问到外部变量的根本原因

Now or nerver .
原文地址:https://www.cnblogs.com/iyueyao/p/3291200.html