1

I was using setInterval() and I came across some strange behavior. To illustrate this better, I made a function that simply outputs a value passed to it and increases it by one.

function increase(i){
    console.log(i++);
}

However, when I try to use this function inside of setInterval(), it fails to update the variable i.

let i = 0;
setInterval(increase, 1000, i);

When I run that, I simply get 0 printed out every second. However, if I modify the increase function to not take in any arguments, I get the correct output

function increase(){
    console.log(i++);
}

Using this version of the function, I get an output of 0, 1, 2, 3... Does anyone have any idea of why that is? I imagine it has to do with the scope of the function, but I'm really not sure what's going on. Is there a way that I can have a function inside of setInterval that takes in an argument and changes it? Or do I simply have to change my function to not receive any arguments and set it to change a variable in the global scope?

  • 1
    When JavaScript is looking for `i` for your `console.log()`, it searches for it from the inner scope outwards. It sees the `i` declared in the function scope first (the argument `i`) before the one on the outer scope (`let i`). Since the one in `increase` is redefined on every iteration of `setInterval`, it will always start be zero (or `undefined` coerced to 0). Removing the `i` inside the function lets the script "see" the `i` defined in the outer scope. – Joseph Mar 15 '21 at 18:01

3 Answers3

0

It is because by passing 'i' into the function, you are not passing a reference to the global variable, rather a copy is being created.

Therefore console.log(i++) is incrementing the copy - every time it is passed in it is zero because the global variable is not updated.

0

In order to update a (referenced) variable outside of a function call, you will need to scope it. I wrapped the i variable inside of a state object. The i param is no longer the same variable as the global i once you create a locally scoped variable of the same name.

You cannot reassign a variable inside of a function, if it is not the original global variable.

let globalState = { i: 0 };

const increase = localState => {
  console.log(localState.i++);
}

setInterval(increase, 1000, globalState);
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • 1
    @MdMahamudulHasan I think you commented on the wrong post, mate. – Mr. Polywhirl Mar 15 '21 at 18:15
  • Ah, I see. I thought that I was only passing a reference to the increase function. Now I see that I was creating a locally scoped variable at "increase(i)". So just to clarify, when passing a primitive argument to a function, you are passing by value right? And non-primitive values are passed by a copy of a reference? – Christian Bernal Mar 15 '21 at 19:57
  • @ChristianBernal primitive types cannot be reassigned, since they are copied into the function call as local variables. On the other hand, objects passed into a function can be referenced, but not reassigned. – Mr. Polywhirl Mar 15 '21 at 21:00
0

the main reason,

function increase(i){
    console.log(i++);
}

here, i is the local variable, so every call i is 0.

but when you are using like below,

function increase(){
    console.log(i++);
}

here i is global scope variable, so i++ incrementing the i value and storing. and printing accordingly

Mahamudul Hasan
  • 2,745
  • 2
  • 17
  • 26