执行上下文与作用域

147 阅读3分钟

执行上下文与作用域

引子:javaScript在执行语句前,经过一系列的准备,为代码执行创造一个‘教室’——执行上下文
执行上下文的文本环境(lexial Environment),类似教室的点名册
1 执行上下文的创建

1 执行栈(Execution Context Stack)

  • 执行栈栈顶的执行上下文称为当前执行上下文

  • JS代码总是在当前上下文中运行

  • JS代码中需要用到的资源,到当前执行上下文查找 2 4种情况会创建新的执行上下文

  • 进入全局代码

  • 进入function函数体代码

  • 进入eval函数参数指定的代码

  • 进入module代码

2 执行上下文运作过程

Step 1: 创建全局执行上下文,并加入栈顶

Step 2: 分析:

  • 找到所有的非函数中的var声明
  • 找到所有的顶级函数声明
  • 找到顶级let const class声明
  • 找到块中声明的,函数名不与上述重复 ({}中) (3.4块作用域)

Step 3: 名字重复处理

  • let const class 声明的名字之间不能重复
  • let const class 和var function 的名字不能重复
  • var和function名字重复的function声明名字优先

Step 4: 创建绑定

  • 登记并初始化var为undefined
  • 顶级函数声明:登记function名字,并初始化为新创建函数对象(函数对象'体内'会保存,函数创建时的执行上下文的文本环境)
  • 块级中函数声明:登记名字,初始化为undefined
  • 登记let const class ,但未初始化

Step 5: 执行语句

// 1. var和function 声明创建在全局对象中,而let const class 声明创建在全局scope中
// 2. 先到全局scope中找变量,查找不到再到全局对象中查找
    console.log(Function);
    console.log(window.Function);
    // 打印结果一致
    let Function = 'abc'
    console.log(Function);//重新被定义在全局scope中
    console.log(window.Function);
3 作用域

3.1 作用域是解析(查找)变量名的一个集合,就是当前运行上下文(也可以是当前上下文的词法环境)

  • 全局作用域就是全局运行上下文
  • 函数作用域就是函数运行上下文

3.2 函数调用时的执行上下文看'身世' ——函数在哪里创建,就保存哪里的运行上下文

函数的作用域是在函数创建的时候决定的而不是调用的时候决定

3.3 并非根据调用嵌套形成(运行上下文)作用域链,而是根据函数创建嵌套形成作用域链,也就是函数的书写位置形成作用域链,以此称为词法作用域

3.4 块级作用域

Step 1:创建新的记录环境,链接在原来记录之前

Step 2:分析:

  • 所有的顶级函数声明
  • 找到let const 声明

Step 3:

  • function和let const 名字不重复
  • let const 之间名字不重复

Step 4: 创建绑定

  • 登记function名字,并初始化为新创建函数对象
  • 登记let const 但未初始化

Step 5: 执行语句

块级作用域声明函数
// 找到块中声明,函数名与 let var function const  等重复,那么对块中函数不做处理,如果没重复,就在全局对象当中创建一个以函数名为名的变量,并把它初始化为undefined
// 执行到块级作用域时,会找let const 登记function ,并创建新的函数对象,记录块级作用域的文本环境,并到全局对象中查找是否有一个名字相同的变量,有的话把值赋值给这个变量,没有的话不做任何处理
总结

image-20220101233152048.png