用 let 定义的变量未在同一作用域 IIFE 中定义

a variable defined with let is not defined in a same scope IIFE

我在下面有一些代码。我希望它可以正确记录 ab,但结果,它记录 a 为 1, b is not defined with error:

Uncaught ReferenceError: b is not defined

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

如果我更改代码使 bar 作为函数声明,一切都很好

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

我对函数作用域、块作用域、提升有所了解。但我真的不明白是什么让 b 变成 'not defined'

上面的所有代码都是 运行 在 Chrome 66 的 devTools

这是不依赖自动分号插入 (ASI) 的原因之一,除非您和每个可能会处理代码的程序员都非常清楚规则ASI.

您的代码试图将 2 作为函数调用,将调用您的 bar 函数的结果作为参数传递,因为以下 IIFE 周围的 () 可以合理地(通过 ASI规则)被视为 let b = 语句的一部分。由于调用 bar 发生在声明 b 之前(直到其初始化程序运行后才声明),您会收到错误消息。

如果我们稍微更改一下换行符,您就可以看到发生了什么:

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

添加 ; 修复它:

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