词法环境

# 定义 (opens new window)

词法环境(lexicalEnvironment) 是一个用于定义特定变量和函数标识符在 ECMAScript 代码的词法嵌套结构上关联关系的规范类型。一个词法环境由一个环境记录项和可能为空的外部词法环境引用构成。通常词法环境会与特定的 ECMAScript 代码相联系(如 FunctionDeclaration,WithStatement 或者 TryStatement 的 Catch 块这样的语法结构),且类似代码每次执行都会有一个新的语法环境被创建出来。

# 理解为

  • 词法环境用来保存变量和标识符的映射关系
  • 组成:
    • 环境记录项: 存储变量和函数声明的位置
    • 外部环境引用: 对外部或者父级词法环境的引用,全局指向null
  • 每执行代码就会创建新的词法环境
lexicalEnvironment = {
  // 环境记录项
  environmentRecord: {
    <identifier>: <value>,
    <identifier>: <value>,
    ...
  },
  // 外部环境引用
  outer: <Refernce to the parent lexical environment>
}

# 举个🌰

const globalTxt = 'global execution context'

function fn() {
  const fnTxt = 'Inside Lexical Environment'
}
fn()
  • 当js创建全局上下文执行全局代码时,会创建新的词法环境,保存全局定义的变量和函数
// 全局的词法环境可解释为
globalLexicalEnvironment = {
  environmentRecord: {
    globalTxt: 'global execution context',
    fn: <refernce to function object>
  },
  outer: null // 全局已经是最外层,所以没有外部环境引用
}
  • 当js创建为函数创建执行上下文时,会再创建一个新的词法环境,保存函数执行时定义内部的变量
// fn的词法环境可解释为
functionLexicalEnvironment = {
  environmentRecord: {
    fnTxt: 'Inside Lexical Environment'
  },
  outer: <globalLexicalEnvironment> //引用父级的词法环境
}

函数执行完毕后,它的执行上下文从堆栈中删除。词法环境就不一定被删除,取决于该词法环境是否被其外部词法环境属性中的任何其他词法环境引用,如闭包

# 思考🤔

# 变量环境、词法环境、执行上下文(this)和通过作用域查找某个变量是怎样的过程?

var global_variable1 = 'Global Variable1'
let global_variable2 = 'Global Variable2'

function fn() {
  var inside_variable1 = 'Inside Variable1'
  let inside_variable2 = 'Inside Variable2'
  {
    var block_variable1 = 'Block Variable1'
    let block_variable2 = 'Block Variable2'
    console.log(block_variable2, inside_variable2, global_variable2)
  }
}
fn()

// 实际执行顺序
// 全局代码
var global_variable1
fn
gloable_variable1 = 'Global Variable1'
let global_variable2 = 'Global Variable2'
fn = function() {}
fn()

// 函数内部
var inside_variable1
var block_variable1
inside_variable1 = 'Inside Variable1'
let inside_variable2 = 'Inside Variable2'
{
  block_variable1 = 'Block Variable1'
  let block_variable2 = 'Block Variable2'
}

img

# 总结

  • 词法环境是js创建执行上下文时,被创建用来保存变量和函数声明的环境
  • 作用是使代码在执行期间,可以访问到保存在其内部的变量和函数
  • 代码执行完毕后,从内存中释放掉
  • 通过 var 定义的变量,存在于变量环境