Home > other >  Return value evaluation of a stored function inside a loop with let variable
Return value evaluation of a stored function inside a loop with let variable

Time:01-19

To my understanding, if the loop variable of a for loop is defined with var, then any change on that variable is applied globally. for example:

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

In the above code, 3 will be printed into the console. Because in the last iteration the variable i will equal to 3. Therefore when printNumTwo is called, the update i will be returned. However if I use let this is not the case and the following behavior happens:

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

The above code will print 2.

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

however, the above code prints 3. What is the reason for this?

source: The first two code blocks are from here.

CodePudding user response:

In the first example, var scopes i to the function, so at the end of the loop i changes i from 2 to 3 and the loop stops. The only i is now 3 and printNumTwo returns i which is 3.

In the second example let scopes i to the block, so the function assigned to printNumTwo closes over it. The last time the body of the loop runs, i is 2 and printNumTwo returns i which is 2. (A new i is created with the value 3 but no function is created that uses it).

In the third example, let scopes i to the block and the same thing happens except you have i = 3; which changes every i to 3. So the last function that is created (as well as the previous ones which are overwritten) returns i which is 3.

CodePudding user response:

however, the above code prints 3. What is the reason for this?

Because you assign 3 to the i variable that printNumTwo closes over. It doesn't matter that the assignment happens after printNumTwo is created, only that it is the variable that printNumTwo is using.

The difference between var and let in for loops is that a new variable is created for the body of the loop on each loop iteration with let. But you're assigning to that variable within the loop body, so the function closing over (printNumTwo) it sees that value later when you call it.

It's exactly like this:

function create(i) {
    // This function closes over `i`
    const fn = function() {
        return i;
    };

    // This modifies the `i` it closes over
      i;

    return fn;
}
const printValue1 = create(1);
console.log(printValue1()); // 2 (1   1)

const printValue27 = create(27);
console.log(printValue27()); // 28 (27   1)


In response to a comment on the question, you've said:

same thing also happens in the second code block (i in the update section in for loop ) but the answer is 2

Ah! Now I see why there's a misunderstanding. You're right that there's an update to i — but it's not the i that printNumTwo closes over.

The update section of the for is performed on the new variable for the next iteration at the start of the next iteration, not on the one for the iteration that just finished at the end of the iteration. It does this:

  • Create a new iteration variable (let's call it iNew)
  • Assign the value of the old iteration variable (let's call it iOld) to the new variable (iNew = iOld)
  • Run the update code using iNew (iNew )

That's why i (the old one) remains 2; it's the new one that becomes 3.

CodePudding user response:

Scope of var is the function and scope of let is the block.

So when assigning value to the printNumTwo function, the value of i is still 2. doesn't matter what happens to i later.

The behavior of var and let you can understand from this example.

for(var i=0; i<3; i  ){
    setTimeout(() => console.log('var', i))
}

for(let i=0; i < 3; i  ){
    setTimeout(() => console.log('let',i))
}

  •  Tags:  
  • Related