js词法作用域

93 阅读3分钟

JavaScript 使用 词法作用域(又称为静态作用域),这是一种确定变量和函数可访问性的机制。以下是关于 JavaScript 词法作用域的详细说明:

特征:

  1. 基于代码结构

    • 词法作用域基于源代码的结构来决定变量和函数的可见性。在编写代码时,根据变量和函数的物理位置(即它们在源代码中的位置)来确定它们属于哪个作用域。
  2. 作用域确定时机

    • 编译阶段:词法作用域在编译阶段(词法分析阶段)就已经确定,这意味着无论函数何时被调用或以何种方式调用,其能够访问的变量和函数都是由其在源代码中的位置决定的。
  3. 作用域层次

    • 全局作用域:顶层作用域,所有在任何函数外部定义的变量和函数都属于全局作用域,可以在整个程序中访问。
    • 局部作用域:由函数创建。每个函数有自己的作用域,其中定义的变量和函数只能在其内部以及其嵌套的作用域中访问。
  4. 作用域链

    • 查找规则

      • 从内到外:当在当前作用域中查找变量或函数时,如果找不到,则会沿着作用域链向上级作用域(如外层函数、直至全局作用域)逐级查找,直到找到目标变量或函数或者到达全局作用域为止。
    • 作用域链构建

      • 每个函数在被调用时,都会创建一个执行上下文,其中包含了作用域链。作用域链是一个对象列表,按照函数定义时的词法层级顺序排列,最前端是当前作用域(活动对象,AO 或 LexicalEnvironment),之后是其外层作用域,直至全局作用域(全局对象,GO 或 GlobalLexicalEnvironment)。
  5. 闭包

    • 概念:当一个函数可以访问并操作其外部作用域(包括其父函数作用域及更外层作用域,直至全局作用域)中的变量时,即使在其外部作用域已经结束执行后,这种现象被称为闭包。
    • 应用:闭包使得函数可以“记住”并操作其词法作用域内的状态,常用于实现数据隐藏、模块化、异步控制、缓存计算结果等场景。
  6. 示例说明

javascript
   // 全局作用域
   var globalVar = "global";

   function outer() {
     // 外部函数作用域
     var outerVar = "outer";

     function inner() {
       // 内部函数作用域
       var innerVar = "inner";

       console.log(innerVar); // "inner"
       console.log(outerVar); // "outer"
       console.log(globalVar); // "global"
     }

     inner();
   }

   outer();

在此例中:

  • inner 函数可以访问其内部定义的 innerVar
  • 它还可以访问外部 outer 函数作用域中的 outerVar,因为 outer 是 inner 的词法父作用域。
  • 最后,inner 能够访问全局作用域中的 globalVar,这是作用域链的最顶端。

结论

JavaScript 词法作用域基于代码的静态结构来确定变量和函数的访问权限。理解词法作用域对于编写清晰、无意外副作用的 JavaScript 代码至关重要,它有助于避免变量遮蔽、理解闭包行为,并有效地利用作用域进行信息隐藏和资源管理。