【问题标题】:Lexical scoping in JSJS 中的词法作用域
【发布时间】:2018-11-05 23:08:45
【问题描述】:

我正在通过阅读作者写道的一本书(Ethan Brown 的《学习 JavaScript》)来学习 JS:

词法范围是指您定义的范围内的任何变量 一个函数(而不是当你调用它时)在 功能。考虑这个例子:

const x = 3;

function f() {
  console.log(x); // this will work
  console.log(y); // this will cause a crash
}
const y = 3;
f();

当我们定义函数 f 时,变量 x 存在,但 y 不存在。 然后我们声明 y 并调用 f ,并看到 x 在范围内 被调用时 f 的主体,但 y 不是。这是一个词法的例子 作用域:函数 f 可以访问标识符 在定义时可用,而不是在调用时可用

当我在 VS Code 调试器中运行它时,似乎没有任何错误。

我明白了

3

3

没有任何例外。这是否取决于我正在使用的 ES 版本或其他?

【问题讨论】:

  • 这是一个糟糕的示例代码。作者完全错了。
  • 补充@Pointy所说的,在定义和编译函数时没有分配范围,而是在运行时分配,即在调用函数时。
  • y 不在f 的范围内,但它被定义在封闭范围内(在本例中为全局范围),因此可以毫无问题地访问它。听起来这本书没有很好地解释范围。 (我所知道的关于 JS 作用域的最佳讨论在这本书中:github.com/getify/You-Dont-Know-JS/blob/master/…)
  • 这里有一个很好的例子,可以帮助你理解词法作用域。 stackoverflow.com/a/1047491/9898651
  • @Pointy 的评论应该是答案。这本书的作者犯了一个错误,没有两种方法。

标签: javascript


【解决方案1】:

虽然我认为作者只是选择了一段糟糕的(嗯,不正确的)代码来说明这一点,但代码很有趣,因为它可以说明一些相关但不同的东西。因为y 是用const 声明的,所以它在函数内部可见,因为它的声明被提升到最近的封闭块(在发布的代码中没有明确可见,但它必须在某处)。但是,如果将函数调用移到该声明之前,您将看到一个错误,因为对y 的引用将发生在名称有点奇怪的“临时死亡”中区”。对使用 let 或 const 创建的已声明但未初始化的变量的引用是运行时错误。

如果 y 的声明更改为 var 声明,则将函数调用移至变量声明之前不会导致错误,因为该变量已定义且在范围内,但只是(老式)未初始化,因此只需undefined。

【讨论】:

  • 正如在这个不错的答案中指出的那样,它的 TLDR 将是 -- variable hoisting 是原因。
【解决方案2】:

这是有效的,因为 const y=3 是在调用 f() 之前声明的。如果您将y 的声明移到f() 之后,那么它将按“预期”

【讨论】:

    猜你喜欢
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 2013-06-26
    • 2017-05-21
    • 2013-11-06
    • 1970-01-01
    相关资源
    最近更新 更多