js作用域链

98 阅读3分钟

JavaScript 中的 作用域链 是一种逻辑结构,用于确定在当前执行上下文中如何查找变量和函数。作用域链确保了对变量的正确访问和隔离,是实现词法作用域的关键机制。以下是对 JavaScript 作用域链的详细说明:

特征:

  1. 定义

    • 作用域链 是一组对象(通常为环境记录项,如活动对象或全局环境)的有序列表,这些对象代表了当前执行上下文及其所有外部词法环境。
  2. 构建

    • 当一个函数被调用时,JavaScript 引擎会创建一个新的执行上下文,其中包括一个新的作用域链。
    • 新作用域链的最前端(即链头)始终是当前执行上下文对应的 活动对象AO)或 词法环境LexicalEnvironment),其中存储了函数内部定义的变量和函数声明。
    • 链的后续部分(即链尾)指向包含当前执行上下文的外部词法环境,通常是定义该函数的作用域。这个过程会一直延续到全局作用域(全局对象,GO 或 GlobalLexicalEnvironment),形成一个从内到外的链式结构。
  3. 查找规则

    • 从内到外:当在当前作用域中查找变量或函数时,引擎会首先检查当前作用域链的最前端(活动对象)。如果在那里找不到目标变量或函数,则沿着作用域链向后移动,检查下一个对象(外部作用域的词法环境),依此类推,直到找到变量或函数,或者遍历完整个作用域链仍未能找到。
  4. 闭包与作用域链

    • 当一个函数返回另一个内部函数时,内部函数会保留对其外部作用域(包括其父函数作用域及更外层作用域,直至全局作用域)的访问权,即使外部函数已经执行完毕。这种情况下,内部函数的作用域链包含了外部函数的作用域,形成了闭包。
    • 闭包使得内部函数可以访问并操作其外部作用域中的变量,即使这些变量在外部函数执行完毕后本应“消失”。闭包是 JavaScript 中实现数据封装、私有变量、异步处理等高级功能的重要工具。
  5. 示例说明

javascript
   function outer() {
     var outerVar = "outer";

     function inner() {
       console.log(outerVar); // "outer"
     }

     return inner;
   }

   var innerFunc = outer();
   innerFunc(); // 输出 "outer"

在此例中:

  • outer 函数被调用时,创建了一个新的执行上下文,其作用域链包括活动对象(存储 outerVar)和全局作用域。
  • inner 函数在 outer 函数内部定义,其作用域链在创建时包含了 outer 的活动对象(含 outerVar)和全局作用域。
  • outer 函数返回 inner 函数并赋值给 innerFunc,此时 outer 函数执行完毕,但 inner 函数保留了对 outer 作用域的访问(通过其作用域链)。
  • 当调用 innerFunc() 时,尽管 outer 已经结束,inner 仍能通过作用域链访问到 outerVar 并输出。

结论

JavaScript 作用域链是一种关键机制,它确保了变量和函数的正确访问,支持词法作用域原则,并通过闭包实现了跨作用域的数据访问和状态保持。理解作用域链有助于深入理解 JavaScript 中的变量查找、作用域隔离、闭包行为以及相关的编程模式。