JS上下文和作用域

55 阅读2分钟

1,执行上下文

执行上下文是指代码运行的环境。每个上下文都有一个关联的变量对象,这个上下文中定义的所有变量和函数都存在于这个对象上。

  • 函数执行上下文:函数执行时关联的上下文对象为AO(Activation Object)。函数执行上下文会在函数调用时创建
  • 全局执行上下文:也表示全局作用域,GO(Global Object)
    • 在浏览器环境下时window对象
    • 在nodejs中时global对象

2,声明提升

JavaScript 提升是指解释器在执行代码之前,似乎将函数、变量、类或导入的声明移动到其作用域的顶部的过程。

  • 由function声明的函数和var定义的变量,会被进行提升
  • 赋值语句的函数不会被提升,如 const foo = function(){}
  • var声明的变量被提升后,默认值为undefined,提升时不会赋值
  • 函数会首先被提升,然后才是变量
  • function*,async function,async function*声明也会被提升

3,作用域

  • 作用域是指变量在程序中可访问的区域
  • 作用域分为全局作用域,函数作用域,块级作用域
    • ES6引入了let和const声明方式,使得JavaScript拥有了块级作用域。块级作用域是指变量或函数仅在它们被声明的块({})内部可见。
  • 作用域链是由多个作用域组成的链式结构
  • 在查找变量和函数时,会沿着作用域链向上查找,直到全局作用域
  • 内部作用域可以访问外部作用域的变量,但外部作用域不能访问内部作用域的变量。

4,预编译

全局预编译

  1. 创建全局执行上下文GO
  2. 函数声明提升
  3. var声明的变量提升,值为undefined
  4. 运行代码

函数预编译

  1. 创建执行上下文AO
  2. 函数内声明的函数和变量提升
  3. 声明形参
  4. 实参与形参绑定
  5. 运行代码

看一道示例题目,输出1,2,2

  1. 函数内声明和变量提升,所以此时function b和var c被提升
  2. 声明形参a,b,赋值实参的值1,undefined 所以此时 a=1,b=undefined
  3. 继续向下执行console.log(a);输出 1
  4. a被赋值3,b被赋值2 所以后面两个都是输出2
function fn(a,b){
    console.log(a);
    c =0
    var c;
    a=3
    b=2
    console.log(b);
    function b(){}
    console.log(b);
}
fn(1)

5,调用栈

  • 调用栈是一种数据结构,用于跟踪函数的调用顺序和状态。
  • 每当一个函数被调用时,其执行上下文会被推入调用栈。
  • 当函数执行完毕,其上下文则从栈顶弹出,控制权返回到调用它的上层函数作用域或全局作用域。