跳到主要内容

词法环境

在JavaScript中,词法环境(Lexical Environment)是一个非常重要的概念,它与变量的作用域、生命周期以及闭包的实现密切相关。

什么是词法环境

词法环境是一个规范类型,用于定义如何存储在代码中定义的变量和函数。每个执行上下文(例如,执行一个函数时)都有一个与之关联的词法环境。

词法环境的组成

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

  1. 环境记录(Environment Record)
    • 这是存储变量和函数声明的实际位置。
    • 环境记录自身分为两种类型:
      • 声明式环境记录:用于存储变量和函数声明,通常用于函数作用域和块级作用域。
      • 对象环境记录:与全局环境相关,通常与全局对象(如window)关联。
  2. 外部词法环境引用(Outer Lexical Environment Reference)
    • 这是指向包含当前词法环境的外部词法环境的引用。这是实现词法作用域和闭包的关键。
lexicalEnvironment = {
environmentRecord: {
// 声明式环境记录
declarations: {
// 变量声明
var1: undefined,
// 函数声明
func1: function func1() {}
},
// 外部环境引用
outer: <Reference to the outer environment>
},
}

示例

下面是一个简单的示例,展示了词法环境的结构:

const text = 'Hello Lexical Environment'

function fn() {
const fnText = 'Inside Lexical Environment'
console.log('Inside function')
}
fn();
console.log('Inside global execution context')

当JavaScript创建一个全局执行上下文来执行全局代码时,它会创建一个新的词法环境来存储全局变量和函数声明。在这个例子中,全局词法环境包含一个变量text和一个函数fn。所以这个全局词法环境就有:

lexicalEnvironment = {
environmentRecord: {
declarations: {
text: 'Hello Lexical Environment',
fn: < reference to function object >
},
outer: null
}
}

这里是全局作用域下的词法环境,所以外层是null

当JavaScript执行fn()函数时,它会创建一个新的执行上下文来执行函数内部的代码。这个新的执行上下文会有一个新的词法环境来存储函数内部的变量和函数声明。在这个例子中,函数fn内部的词法环境包含一个变量fnText。所以这个函数内部的词法环境就有:

lexicalEnvironment = {
environmentRecord: {
declarations: {
fnText: 'Inside Lexical Environment'
},
outer: < reference to global lexical environment >
}
}

这里是函数作用域下的词法环境,所以外层是全局词法环境。

提示

当函数执行完成时,它的执行上下文会从执行堆栈中弹出,但是它的词法环境不一定会被销毁。这是因为函数内部的词法环境可能会被其他函数引用,这就是闭包的实现原理。

总结

JavaScript引擎创建一个执行上下文的时候,创建的词法环境是JavaScript中存储变量和函数声明的地方。它由环境记录和外部词法环境引用组成。词法环境是实现词法作用域和闭包的关键。

注意

通过 var 定义的变量存放在变量环境中,通过 letconst 定义的变量存放在词法环境中。