词法范围问题

Lexical Scoping Issue

我正在阅读“你不懂 JS”系列中的书 'Scope & Closures',我读到函数先被提升,然后是变量。 浏览此代码片段:

function foo() {
    var a = 2;
    function bar() {
        console.log( a ); // 2
    }
    bar();
}
foo();

如果是这种情况,是否应该不将函数 bar() 提升到顶部并且这段代码会产生错误?因为吊装之后这段代码应该是这样的(至少我理解的是这样)

function foo() {
    function bar() {
        console.log( a );
    }
    var a;
    a = 2;
}

这是因为函数被提升到最前面和后面的变量。如果不是这样,请指正。

它们都被吊起来 一直到顶部,所以 abar 的范围内;这并不是说函数是 "above" 变量。只有当函数声明和变量具有相同的名称时,顺序才会起作用,在这种情况下,函数声明获胜,因为当变量被提升时,如果已经存在具有给定名称的绑定,则不会创建它。

"Hoisting" 是一个方便的 shorthand 术语,但它不是字面意思。当 foo 被称为 时会发生什么(省略一些细节以关注问题中的问题) 是:

  1. 为调用 foo
  2. 创建了一个 执行上下文
  3. 在该上下文中创建一个对象来保存 "bindings" 用于该上下文执行的标识符(如您的示例中的 bara
  4. 处理所有函数声明并将其标识符的绑定添加到对象(如果有多个同名声明,最后一个优先)
  5. 处理所有变量声明并将它们的标识符添加到对象如果对象还没有它们的绑定

然后该对象用于处理执行上下文中的绑定(例如,在引用 a 时使用与绑定关联的值,并在设置 a 时设置,等等.).

hoisting 在编译部分完成,而 bar 函数的编译直到被调用才完成。那么为什么 bar 应该显示错误。 如果您想进一步了解有关 javascript 是如何编译或执行的详细信息。这是一个不错的视频https://www.youtube.com/watch?v=QyUFheng6J0