I have some code below. I hope it can log a
and b
correctly, but as the result, it logs a
as 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());
If I change the code to make the bar
as a function declaration, every thing is fine
function foo(){
var a = 1
let b = 2
function bar() {
console.log(a)
console.log(b)
}
bar()
}
console.log(foo());
I know some thing about function scope, block scope, hoisting. But I really don't understand what happens make the b
to be 'not defined'
All the code above was run in the Chrome 66's devTools
This is one of the reasons not to rely on Automatic Semicolon Insertion (ASI) unless you and every programmer who might conceivably work on the code are very clear on the rules for ASI.
Your code is trying to call 2
as a function, passing in the result of calling your bar function as an argument, because the ()
around the following IIFE can be reasonably (by ASI rules) considered part of the let b =
statement. Since calling bar
happens before b
is declared (it's not declared until after its initializer runs), you get the error.
If we change the line breaks a bit you can see what's going on:
function foo(){
var a = 1
let b = 2(function bar() {
console.log(a)
console.log(b)
}());
}
console.log(foo());
Adding the ;
fixes it:
function foo(){
var a = 1;
let b = 2;
(function bar() {
console.log(a);
console.log(b);
}());
}
console.log(foo());