在 JavaScript 中,词法环境(Lexical Environment) 是 JavaScript 解释器在执行代码时创建的一种内部数据结构,用于存储变量和函数的作用域信息。

一个词法环境由两个主要部分组成:

  1. 环境记录(Environment Record)
    • 记录变量、函数等标识符的绑定。
  2. 外部环境引用(Outer Environment Reference)
    • 指向外部词法环境(即上层作用域),用于实现作用域链。

1. 环境记录(Environment Record)

环境记录存储变量和函数声明,不同类型的环境记录有不同的存储方式:

  • 声明式环境记录(Declarative Environment Record)

    • 用于存储 letconstfunction 声明的变量。
    • 例如在函数作用域或块级作用域内,变量会存储在此环境记录中。
  • 对象环境记录(Object Environment Record)

    • 主要用于 var 声明的变量,它们会被存储在全局对象(如 windowglobalThis)中。
    • 例如,全局作用域的 var 变量和 function 声明会挂载到全局对象上。

示例:

var globalVar = 1;   // 存在于对象环境记录中(window.globalVar)
let blockVar = 2;    // 存在于声明式环境记录中
const blockConst = 3; // 存在于声明式环境记录中
function test() {}   // 存在于对象环境记录(在 `var` 方式下)或声明式环境记录(在 `let/const` 方式下)

2. 外部环境引用(Outer Environment Reference)词法环境-outer

  • 用于指向外部(上层)词法环境,形成作用域链(Scope Chain)
  • 作用域链的查找是逐层向上查找,直到全局作用域。

示例:

function outer() {
  let a = 10;
  function inner() {
    let b = 20;
    console.log(a + b); // `inner` 作用域的词法环境会引用 `outer` 作用域
  }
  inner();
}
outer();

inner 函数的词法环境中:

  • 环境记录:存储 b
  • 外部环境引用:指向 outer 作用域的词法环境,其中存储 a
  • 作用域链innerouter全局

词法环境的类型

  1. 全局环境(Global Lexical Environment)
    • 最顶层的环境,变量存储在全局对象上(如 window)。
  2. 函数环境(Function Lexical Environment)
    • 每个函数调用都会创建新的词法环境,存储参数、局部变量等。
  3. 块级环境(Block Lexical Environment)
    • letconst 变量会在块级作用域({} 内)创建一个新的词法环境。

示例:

let x = 10; // 全局环境
 
function foo() {
  let y = 20; // 函数环境
  if (true) {
    let z = 30; // 块级环境
  }
}
foo();

总结

词法环境的属性作用
环境记录存储变量、函数等标识符的绑定
外部环境引用指向外部作用域,形成作用域链
全局环境作用域最顶层
函数环境每个函数调用都会创建新的词法环境
块级环境letconst 形成的局部作用域

这就是 JavaScript 词法环境的核心概念,它是 JS 作用域和闭包的基础。