0

I am new to JavaScript, and recently stumbled across this problem questioning what would be printed to the console. The correct answer is 4 4 4 4, because of pass-by-reference. However, I don't understand how this is the result. Why does pass-by-reference dictate the output if the output is simply a value of i that seems only dependent upon an iteration of a for-loop?

const array = [10, 21, 31, 41];

for(i = 0; i < array.length; i++) {
  setTimeout(function print(array){
      console.log(i)}, 3000);
}
1
  • Pass-by-reference has to do with function arguments, and the only one you have in your code, is not used. The output has nothing to do with pass-by-reference or not, but with asynchronous code. Commented Nov 28, 2017 at 21:03

5 Answers 5

2

Okay, step by step:

const array = [10, 21, 31, 41];

for(i = 0; i < array.length; i++) {
  setTimeout(function print(array) { /* stuff... */ }, 3000);
}

// When we get to here, the value of i is 4.

When this snippet runs, we iterate the array, and set a timeout for each iteration. When the for loop is finished, we have called setTimeout four times, but none of the functions given to setTimeout have run. Indeed, they won't run for another 3 seconds.

Most importantly, at this point, the value of i is 4.

Three seconds later...

Finally, our function print that we gave to setTimeout is going to run. So what does that function look like?:

function print(array) { console.log(i); }

Now recall the value of i is now 4. So it prints 4, four times. This is because it is when the function actually executes that it reads the value of the variable i, not when the function was declared.

Basically, i is 4 at the time that your function print is actually invoked, so therefore, it unsurprisingly prints 4.

Sign up to request clarification or add additional context in comments.

Comments

1

Look again at the inner function which is being called by the timeout.

function print(array){
    console.log(i);
}

At no point is the passed in array actually used for anything, in fact the following code will do exactly the same thing (print 4 4 4 4)

for(i = 0; i < array.length; i++) {
  setTimeout(function print(){
      console.log(i)}, 3000);
}

The pass by reference part means that it isn't the value of i which is passed in to the print() function, but a reference to whatever value is held by i at the time console.log(i) is called. Since there is a 3 second delay, the loop has more than enough time to finish and the value of i is 4 by the time the first console.log(i) is called. You can even set the value of i after the loop and it will change the result.

for(i = 0; i < 4; i++) {
  setTimeout(function print(){
      console.log(i)}, 3000);
}

i = "foo";
// prints foo foo foo foo

Comments

0

Your setTimeout makes your code async, wenn the timeout of 3000 is gone the javascript loop is ended before and the last value of the index will be toke also the number 4. Search for 'js Eventloop' and you will discover more about, how the Browser works in a nutshell.

Comments

0

There's only a single value of i. Calling setTimeout doesn't store the original value anywhere.

Because the print function is called after the for-loop has finished running, the value of i will be 4 because it's the value it'll have at the end of the for-loop.

Comments

0

To be able to use 'i' value you need something called closure. When the function execute at that time i value became 4 and it gets printed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.