getify / You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.
Other
179.29k stars 33.48k forks source link

IIFE scope is not empty #1708

Closed ghost closed 3 years ago

ghost commented 3 years ago

Edition: 1st

Book Title: Scope & Closures

Chapter: 5

Section Title: Loops + Closure

Problem: I ran this snippet of code in my browser, Google Chrome, and it works just fine.

for (var i=1; i<=5; i++) {
    (function(){
        setTimeout( function timer(){
            console.log( i );
        }, i*1000 );
    })();
}

apparently, the scope is not empty!!

I'm confused 🤔

JaykeyGuo commented 3 years ago
for (var i=1; i<=5; i++) {
    (function(i){
        setTimeout( function timer(){
            console.log( i );
        }, i*1000 );
    })(i);
}

You need take i into IIFE

getify commented 3 years ago

@osaimi if you run your snippet, you'll get this result:

for-loop-1

It doesn't fail, but it's not right either, as the "expected" outcome is this (from @JaykeyGuo's snippet illustrates):

for-loop-2
ghost commented 3 years ago

But it shouldn't even work because IIFE creates a new scope that doesn't have 'i'.

Am I missing something here?

ghost commented 3 years ago

I changed var to let for the sake of experiment and if behaved as expected!!

Capture

getify commented 3 years ago

Creating an IIFE that has no declared variables in it is a no-op... it has no effect... as your initial snippet showed. If you removed the IIFE, nothing would change.

Using let creates a different kind of binding (block scoping) per iteration, so again the IIFE is completely irrelevant... take it out or leave it, makes no difference. An empty scope is no different than no scope at all, in this respect.

ghost commented 3 years ago

It makes sense now. Thank you @getify