【问题标题】:How can javascript have lexical scope if scope is assigned at runtime?如果在运行时分配范围,javascript如何具有词法范围?
【发布时间】:2020-04-23 22:46:01
【问题描述】:

我对 javascript 具有词法范围感到困惑。

词法作用域:词法作用域意味着在您定义函数的作用域内(与调用它时相反)的任何变量都在函数的作用域内。

但是在 JS 中它的: 范围不是在定义和编译函数时分配,而是在运行时分配,即在调用函数时分配

在下面的例子中:如果 JS 有词法作用域,我会得到一个错误。但是我没有因为提升和运行时 js 引擎检查 x。

function f() {
 console.log(x);
}
const x = 10;
f(); // 10

有人可以用一个例子来解释一下 JS 如何具有词法范围吗?谢谢!

【问题讨论】:

    标签: javascript scope lexical-scope


    【解决方案1】:

    但是在 JS 中,它的作用域不是在定义和编译函数时分配,而是在运行时分配,即在调用函数时分配

    我认为您对 JS 中范围的这种描述感到困惑。 this article 给出了更准确的 JS 范围描述(强调添加):

    因为此时也定义了函数(词法分析阶段),我们可以说词法范围是基于作者时变量和范围块存在的位置,因此在词法分析阶段结束时被锁定。 范围不是在运行时定义的,而是可以在运行时访问的。

    所以,在你的例子中:

    function f() { 
      console.log(x); 
    } 
    const x = 10; 
    f(); // 10
    

    正在发生的事情是函数f 的作用域链包括:

    • 它的本地范围
    • 外部的全局范围

    并且这个“范围链”是在作者时定义的(即词法范围)。

    在创作时,常量x是在全局范围内定义的,当f被调用时,x在全局范围内是可用的。声明(但未调用)函数 f 时未定义 x 与此讨论无关。

    另外,当你提到关于代码示例的“提升”时,你是不正确的:使用 const 声明的变量没有被提升。

    如果我们改变你的例子,我们会得到一个引用错误,因为常量 x 没有在全局范围内初始化(即在作者时间),当函数 f 被调用(和函数 @987654332 @ 查看其范围链,该范围链已在作者时间定义):

    function f() { 
      console.log(x); 
    } 
    f(); // 10
    const x = 10; 
    

    【讨论】:

      【解决方案2】:

      参见下面的示例,函数f 之外的所有内容都被编译并且变量被提升。 但是函数f 中的内容在被调用之前不会被提升/解析。并且f 中的局部变量在函数内仍然可以访问(即函数的词法范围)。

      function f() {
        console.log(x);
        var a = 20;
      }
      
      const x = 10;
      
      f(); // 10
      
      
      console.log(a);

      【讨论】:

        猜你喜欢
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-25
        • 1970-01-01
        • 2015-09-13
        • 2019-11-11
        • 1970-01-01
        相关资源
        最近更新 更多