ES6: var & let comparison

I couldn’t follow the explanation given in the example of challenge " ES6: Compare Scopes of the var and let Keywords". Can someone explain?

It says that if we use var in the for loop, the function printNumwo returns 3 and not 2. I don’t understand the reason? Ain’t we were doing this in all ES5 challenges?

@Yogita25, could you please provide the code itself

@snigo, here is the link to the problem

I’m going to quote a post I made on a similar question:

This gets asked a lot, because I suspect we don’t necessarily explain very well what actually happens around a for loop

This is going to possibly be a confusing explanation to read but it might help in future for other loop related questions you may have

When we have for(a; b; c){d; } where a, b, c, d are parts of the for loop, the following happens:

  1. The expression a is executed once
  2. b is executed, and if falsy (or false) go to 6
  3. The body of the loop, d, is executed once
  4. c is executed once
  5. go to 2.
  6. continue with the line after the loop body

Note that c is executed before b's test

The different keywords var and let control which scopes a variable is still defined in, and behave differently for variables defined in the a part of the loop, but that’s what this question will end up showing so I’ll leave it here

Edit: Realised my older explanation of a loop is a little inaccurate

Here is the key sentence from that problem:

" When you declare a variable with the let keyword inside a block, statement, or expression, its scope is limited to that block, statement, or expression."

If the let variable is defined inside a function, as in the example below, it has only local scope:

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"

I believe @Yogita25 is more interested why the output of printNumTwo() is changing depending on var vs let. And the answer to this is way more tricky. When using let, it creates a block scope and eventually a closure printNumTwo (sort of a link between block scope of for loop and global scope). When invoked, it executes in that block scope, where i === 2.

On other hand, var doesn’t create block scope and function printNumTwo is declared in the global scope, basically same as like this:

var printNumTwo = function() {
      return i;
}
for (var i = 0; i < 3; i++) {
  if(i === 2){
    // I won't declare anything today!
  }
}
console.log(printNumTwo());
1 Like

It’s not a great example, and yeah the description is confusing if you’re a beginner. It’s quite important though, because understanding JS scope is pretty central to understanding how to program JS.

var is not block scoped, which means that i still lives once the loop has finished. This means you could potentially keep using i [normally happens accidentally] after the loop is over. And it can cause problems with functions inside the loop — particularly if you define a function in the loop.

for (var i = 0; i < n; i++) {
  // use i
}

let is block scoped: once you get past the closing } on that loop, the variable is done with, none of the above problems apply. This is what most people would expect to happen; let is basically var that works sensibly.

for (let i = 0; i < n; i++) {
  // use i
}

The change is quite subtle — its designed to make specific easily made and hard-to-debug errors less common. Use let for for loops, anyway

Thanks @snigo & @DanCouper. I now understand that let helps us distinguish between variables declared in global and local scope. I still have one doubt in the example given (sorry, freecodecamp is not allowing me to paste the link to the page. probably because I am a new user). Here printNumTwo is declared in global scope and then used inside the for loop. What is I declare the variable printNumTwo inside the for loop? I mean is there any specific reason because of which we are declaring the variable in global scope?

Thanks pulamusic. My understanding is better than earlier after going through the discussion in the post.