Variable scope and a function problem


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

I’ve got 3 questions:

1- I did not understand how a function can be defined without a name and on top of that assigned to a variable, in this case how is it being called? Is it being called at the same time of definition?

2- If we were to replace the var keywords with let keywords and define the i variable globally outside the door loop, we would get the same result, right? Apart from this question, from what I understood: the i variable is defined globally because we’re using the var keyword, but I am not getting how that results in number 2 being returned. Shouldn’t the code iterate through the loop with the values of i being [0, 1, 2] one of them , for each iteration and exit the loop with the global variable i being equal to 3? The only time in the loop shall the code execute the code inside the if statement is when i equals 2, and assigning the variable printNumTwo the returned i in the function which in this case is 2, and there are no other assignment statements changing the value of this variable nor should we go in any other iteration executing the code in the if statement and changing the value of the variable printNumTwo.

3- What does the tutorial mean by block, statement or expression in the paragraph below? What is the example for each one of these three, and how are they different from each other?

The let keyword behaves similarly, but with some extra features. 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.

Challenge: Compare Scopes of the var and let Keywords

Link to the challenge:

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

printNumTwo() returned the correct value because three different i variables with unique values (0, 1, and 2) were created by the let keyword within the loop statement.

The tutorial says that this let keyword created three different i variables. Aren’t they just one variable but declared locally to the for loop and updated each iteration?

Challenge:** Compare Scopes of the var and let Keywords

Link to the challenge:

It’s just a function. A function expression in this case. But still just a function

function example1 () {}

var example2 = function () {}

Will work the same

example1()
example2()

from your first question
function can be anonymous mean function without name

example:
let a = function(){
return ‘hello world’;
}
console.log(a());
// output hello world in console
now here i have called function using variable name,
anonymous or function assign to variable are called using variable name;

now about your second and third question for that lets see difference between var,let and const

var =========================

1> has global scope and function scope
ex:
var a = 10;
console.log(a);
//output 10
and global means ,
i can access a anywhere
in my code.

2> function scope
ex:
function myfun(){
var b = 10;
console.log(b);
// output after function call 10 in console
}
but if i access now b outside the function

console.log(b);
now it will throw an error like b is not define

which provers var has a function scope. which means if i declare variable inside function,
using var i can access that variable inside that function only, outside will give me error

let and const ================

let ans const has global scope and block scope

global scope : from above example now you know global scope means you can access your variable anywhere inside your script.

block scope :
first of all what is block ?
in javascript code block means code inside { } this curly brackets

now block scope example:

{
let m = 40;
console.log(m); //here i will get 40
}
console.log(m); // here i will get error like m is not define

from above example its prove that let has block scope and its same for const

example2:
function myfunction() {
let p = 30;
console.log(p);
}
myfunction() // from calling function i will get 30 in console

console.log(p); // from this i will get error like p is not define

i hope you understand, thank you!

Well, it helps, thanks. But still I have the most important part of my question #2 not answered. When I go through the loop with a counter i variable been defined globally and with the if statement executed only when the i variable is equal to 2 shouldn’t the printNumTwo variable only be assigned to 2 and never changed because I can’t access the if statement again on any iteration. The tutorial suggests that the printNumTwo should have a value of 3.

Because it uses var i in the for loop i is treated as a global variable and thus when you finally get around to calling printNumTwo the value of i will be three because that’s the last value it assumed in the for loop. It isn’t returning the value of i at the time the function is defined. It is returning the value of i at the time the function is executed.

Now if you use let i in the for loop instead then each iteration through the loop treats i as local to that iteration and then i will be equal to 2 in the printNumTwo function because that’s the value it has when the function is defined.

That’s one of the big advantages of using let, variables used in loops have the value you think they have when using closures.

If in the condition was i === 1 with the let keyword, would printNumTwo be assigned a 1 in this case?

Let’s take this example to get what are you saying:

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

Would the first console.log print the number 2?
Does the code ignore the if statement in the second console.log and just look at the function definition to execute and return a value? Am I calling a function or printing the value assigned to printNumTwo?
I really can’t get my head around this

Yes.

There is no if statement inside of the console log. If you declare i with var, then the function definition uses the updated value of i at the end of the loop. If you use let, then the function definition uses the value of i from that loop iteration.

I wouldn’t worry about this too much. The ‘big idea’ here is that var can be confusing and let tends to act in a more straightforward fashion.

Just to be clear, printNumTwo is never assigned a number, it is assigned a function that returns the value of i. And yes, if using let then i would have the value 1 when the function is eventually called.

As @JeremyLT pointed out, yes, because at that time i is set to the value 2 because it is still in the for loop iteration where the value of i is 2.

By the time you get to the second console.log the for loop has terminated so the if statement inside of the for loop basically doesn’t exist at that point and thus is not a factor any more. The printNumTwo variable will have been set to a function and the console.log calls that function.

As stated above, the value assigned to printNumTwo is a function, so you are invoking a function with printNumTwo(). If it wasn’t a function then you would get a TypeError when you tried to do that.

I’d also recommend that you answer these questions for yourself by doing your own testing. There are a ton of websites that allow you to test code, for example the Javascript Playground. Or you could install Node.js on your computer and run JS from the command line. Sure, you can learn from what we say but I think it will stick better if you actually learn from your own testing.

1 Like

Thanks a lot for the help, just a little question: when I use let instead of the var keyword, the console.log(printNumTwo()) call the function assigned to the printNumTwo variable (this function should return the value of i at that point), right? and since the for loop has terminated and the i variable is local to the block, shouldn’t this expression returns an error because i is not defined in that scope?
I am so sorry for the lots of questions I’ve been asking, but I get too annoyed if I don’t understand something well enough.

Ahh, that’s the miracle of closures. When the function inside of the for loop is created, any variables that the function has access to (such as i) are bundled together with the function into a closure. When the function is called at a later time the closure allows it to access those variables. Those variables in the closure stick around even after the code they are local to has already completed. So when you invoke printNumTwo() it can still access the variable i from the for loop because of the closure. In other words, the variable i is still in the functions scope even though the for loop has terminated.

And how does the function determine the value of i in this case? (The function is only defined when the iteration variable i becomes equal to 2, this function returns the value of i when invoked? is this value of i determined at the time of function definition(2) or when it is invoked it lookup the value of i somehow?

As we have seen, if you use var to declare i in the for loop, then when you invoke the function the value of i is 3 even though it was 2 at the time the function was defined. So what does this tell you about the answer to your question?

at the time it is invoked

1 Like

Why the value of i in the function’s scope when bundled into the closure is 2? is it because that’s the value of i at the time the function is defined?

Because when you use let to declare i in the for loop then that means that i has block scope in the for loop, so in essence, in each iteration through the loop the value of i is unique to that loop. Thus, since i has the value 2 when the function is defined, which creates the closure, then i will have the value of 2 in the closure.

Thank you very much. I took a lot of your time.

No worries. It’s confusing stuff for sure. Takes a while to get it all down.