-2

Look at this code.

function func() {
    let x = 0;
    setTimeout(() => {
        console.log(x);
    }, 3000);
}

func();

My question is why we can access variable "x" inside of setTimeout function. I know sounds stupid but let me explain. As i know whenever function is envoked a new execution context is created and puts inside of a call-stack. This context is where our variable are stored. And when we are trying to access a variable inside a function that was declared somewhere else, js engine goes down the call-stack and tries to find this variable inside one of the "parent's" execution context. BUT, as we all know js in a single-threaded language, which means it executes all async operations only when callstack is empty. So this is where my confusion comes from. How we can access variable "x" inside of a setTimeout callback if

  1. Inside callback's execution context there is not such variable.
  2. Callstack is empty, so js engine cannot traverse it to find such variable

And one more question. When i change my code like this why is it printing 2.

function func() {
    let x = 0;
    setTimeout(() => {
        console.log(x);
    }, 3000);

    x = 2;
}

func();
  • "*When i change my code like this why is it printing 2.*" because `x` is set to zero, then a task is scheduled for 3 seconds later, then `x` is set to `2`. After 3 seconds `x` is still `2`. – VLAZ Aug 01 '21 at 19:12

1 Answers1

0

You've just discovered JavaScript's closures which allows a function to access the surrounding lexical context and maintain it alive while the function itself is alive (while the timeout has not been reached/cleared in your case).

Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • I was 99% sure that this is because of the closure. But i have always thought that closure happens when you return function from another function. So how closure is creating here? – кіріл далекорій Aug 01 '21 at 19:11
  • 2
    Closures happen when an inner function survives past the lifetime of the parent function. Returning the inner function is only way way to do that. – Quentin Aug 01 '21 at 19:27
  • @Quentin not only returning it, also passing it to an external function like it's done with `setTimeout` which keeps a reference on it until the timeout gets reached or cleared. It could also be assigned to some external variable or data structure. – Guerric P Aug 03 '21 at 11:38
  • I made a typo "only way way" should be "only one way" – Quentin Aug 03 '21 at 12:29
  • Oh OK fine then – Guerric P Aug 03 '21 at 12:30