The example is not correct? ES6: Scopes of var and let

The example is not correct? ES6: Scopes of var and let
0

#1

Can someone help me understand why the variable printNumTwo is supposed to be equal to 3 and not 2?

In the example text for this challenge, the code snippet is given below:

var printNumTwo;
for (var i = 0; i < 3; i++){
  if(i === 2){
    printNumTwo = function(){
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 3

It is stated that, “As you can see, printNumTwo() prints 3 and not 2. This is because the value assigned to i was updated and the printNumTwo() returns the global i and not the value i had when the function was created in the for loop.”

I don’t understand why printNumTwo would not be equal to 2. I thought the variable printNumTwo only gets assigned a specific value once and that is when i === 2. printNumTwo is never set equal to a specific value at any other time, regardless of i, correct?

Thank you in advance!

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3559.6 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords


#2

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make easier to read.

See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

Note: Backticks are not single quotes.


#3

In the example, i is a declared globally. printNumTwo is a global variable also. Inside the for loop, printTwo is assigned a function when i == 2. There is a reference to the global variable i inside the function which is assigned, but it does not matter, because i will only be evaluated within the function when the function is actually called. This call takes place in the console.log statement which is after the for loop ends.

When printNumTwo actually gets called, the value of i is 3, because that is why the for loop ended, so since the function just returns the global variable i value, 3 gets displayed in the console.


#4

Using let in the for loop declaration allows you to “lock” in the value of i at the time i is referenced in the function which is returned.

Without let, you would need to use an IIFE (Immediately Invoked Function Expression) to accomplish something similar to have 2 displayed in the console.

var printNumTwo;
for (var i = 0; i < 3; i++){
  if(i === 2){
    (function(currValofI){
      printNumTwo = function(){
        return currValofI;
      };
    })(i); // pass i's current value of 2 to the anonymous function inside the IIFE
  }
}
console.log(printNumTwo()); // displays 2

#5

Thank you for your response!

I am familiar with Java and C, but am new to JavaScript. I believe I have never ran across a block of code like this:

printNumTwo = function(){
      return i;
    };

I believed I understood this code, but I am beginning to think not. Perhaps me being unfamiliar with the step by step execution here is causing my misunderstanding.

I thought that printNumTwo is only tied to i at the moment i = 2, and not at any other moment.


#6

You are just assigning a function to a variable. This is very handy in that you can create new functions by returning functions and assigning them to other variables. For example, you could do the following:

function nameDisplayer(aName) {
  var displayName = function(){
    console.log('My name is ' + aName);
  };
  return displayName;
}

var displayRandell = nameDisplayer('Randell');
displayRandell(); // displays 'My name is Randell'

var displayMike = nameDisplayer('Mike');
displayMike(); // displays 'My name is Mike'

You technically could write the nameDisplayer function as the following and it would have the same result, but naming the function just makes it more readable.

function nameDisplayer(aName) {
  return function(){
    console.log('My name is ' + aName);
  };
}

var displayRandell = nameDisplayer('Randell');
displayRandell(); // displays 'My name is Randell'

var displayMike = nameDisplayer('Mike');
displayMike(); // displays 'My name is Mike'

Lastly, the first example, could also be written as you are normally used to seeing functions declared.

function nameDisplayer(aName) {
  function displayName (){
    console.log('My name is ' + aName);
  };
  return displayName;
}

var displayRandell = nameDisplayer('Randell');
displayRandell(); // displays 'My name is Randell'

var displayMike = nameDisplayer('Mike');
displayMike(); // displays 'My name is Mike'

#7

Thank you for your in depth response. I will look into IIFE’s. I feel like I should understand why the code returns links together printNumTwo and i when i is 3 and not only in the third iteration of the for loop.

I really appreciate your thorough responses!