返回

词法作用域和作用域链详细讲解:掌握变量作用域和函数执行过程

前端

在编程语言中,作用域是指代码中可以访问变量的区域。词法作用域是通过代码结构定义的作用域,而作用域链是在代码执行时确定的。

词法作用域

词法作用域是通过代码结构定义的作用域。在词法分析阶段,编译器会确定每个标识符的作用域。标识符的作用域就是它可以被访问的代码区域。

词法作用域的规则很简单:

  • 标识符的作用域是从它被声明的地方开始,直到代码块结束。
  • 代码块可以是函数、循环体、if 语句体等等。
  • 如果一个标识符在多个代码块中被声明,那么它的作用域是所有这些代码块的并集。
  • 在 JavaScript 中,对象字面量和类也是词法作用域。

作用域链

作用域链是在代码执行时确定的。作用域链是从当前执行的函数开始,一直到全局作用域。每个函数的作用域链中都包含它自己的作用域以及所有父函数的作用域。

这意味着一个函数可以访问它自己作用域中的变量,以及所有父函数作用域中的变量。但是,一个函数不能访问它子函数作用域中的变量。

变量作用域

变量的作用域就是它可以被访问的代码区域。变量的作用域由词法作用域和作用域链共同决定。

  • 全局变量的作用域是整个程序。
  • 局部变量的作用域是它被声明的函数。
  • 参数的作用域是它所在的函数。

函数执行过程

当一个函数被调用时,它的作用域链就会被创建。作用域链是从当前执行的函数开始,一直到全局作用域。

函数执行过程如下:

  • 函数被调用。
  • 函数的作用域链被创建。
  • 函数的局部变量被初始化。
  • 函数体中的代码被执行。
  • 函数执行完毕,它的作用域链被销毁。

例子

var x = 10; // 全局变量

function f() {
  var y = 20; // 局部变量

  function g() {
    var z = 30; // 局部变量

    console.log(x); // 10
    console.log(y); // 20
    console.log(z); // 30
  }

  g();
}

f();

在这个例子中,全局变量 x 的作用域是整个程序。局部变量 y 的作用域是函数 f。局部变量 z 的作用域是函数 g。

当函数 f 被调用时,它的作用域链被创建。作用域链是从函数 f 开始,一直到全局作用域。

当函数 g 被调用时,它的作用域链被创建。作用域链是从函数 g 开始,一直到函数 f 的作用域链。

函数 g 执行完毕,它的作用域链被销毁。函数 f 执行完毕,它的作用域链被销毁。

词法作用域和作用域链的区别

词法作用域是通过代码结构定义的作用域,而作用域链是在代码执行时确定的。

词法作用域的规则很简单:

  • 标识符的作用域是从它被声明的地方开始,直到代码块结束。
  • 代码块可以是函数、循环体、if 语句体等等。
  • 如果一个标识符在多个代码块中被声明,那么它的作用域是所有这些代码块的并集。

作用域链是从当前执行的函数开始,一直到全局作用域。每个函数的作用域链中都包含它自己的作用域以及所有父函数的作用域。

这意味着一个函数可以访问它自己作用域中的变量,以及所有父函数作用域中的变量。但是,一个函数不能访问它子函数作用域中的变量。