Is saying to "assign a closure to a variable" correct in the context of JavaScript?

Viewed 117

I am curious for the line 20 explanation in my example code.

On line 9 variable with name func1 is declared. It's assigned to the closure that is returned by the function foo() invocation.`

I know that the invocation of the function foo() returns both the function bar and the pointer to the variable a which is in its lexical scope. Since closure is a function combined with all of the variables in its lexical scope, including function and class names, can I say that I am assigning the variable func1 to the closure?

Is this explanation uses the right words and not vague? Could you suggest a better and more concise explanation and paraphrase line 20?

function foo() {
  let a = 1;
  return function bar() {
    a += 100;
    console.log(a);
  }
}

let func1 = foo(); 
let func2 = foo();

func1(); // ???
func2(); // ???
func1(); // ???
func2(); // ???

/*
On line 9 variable with name `func1` is declared. 

!! It's assigned to the closure that is returned by the function `foo()` invocation. 

The closure contains a pointer to the variable `a` that is in the lexical scope of the function `bar` that is returned by the `foo` invocation.

On line 10 variable with name `func2` is declared. It's assigned to the value of closure that is returned by the function `bar()` invocation. The closure contains a pointer to the variable `a` that is in the lexical scope of the function `bar`.


Variables accessible through the closure during the `func1` invocation and `func2` invocation are two separate independent variables that just happen to have the same name (`a`). 

That is, this program would print the following to the console:
- 101
- 101
- 201
- 201
*/
2 Answers

I know that the invocation of the function foo() returns both the function bar and the pointer to the variable a

That's not how closure works. Invocation of foo() only returns the function bar, it doesn't returns a pointer to variable a.

Each environment is linked to its outer environment and when javascript can't find a variable in the current environment, it follows the link to the outer environment. This linkage between the different environments is what enables closures.

When function foo is defined, javascript saves the link to the global environment on the function in a slot which the spec calls [[Environment]] slot of the function.

When the function foo is called, a new environment is created for that call and it is linked to the environment that is saved in the [[Environment]] slot on the function foo (Lets call this environment EnvFoo.)

Similarly, when bar function is defined, javascript saves the link of the environment (EnvFoo) that was created when function foo was called, in the [[Environment]] slot on the bar function. When bar is called, a new environment is created (lets call this environment EnvBar) and it gets a link to the environment saved in [[Environment]] slot on the bar function (EnvFoo), as its outer environment.

So when you call bar function, variable a doesn't exists in the current environment (EnvBar), so javascript looks for the variable a in the outer environment of the current environment, i.e. EnvFoo. This environment contains the variable a, so it get the value of a from this outer environment, i.e. EnvFoo.

This is how closures work, i.e. each environment keeping a reference to its outer environment and when javascript can't find a variable in the current environment, it follows a link to the current environment's outer environment and looks for the variable there. It continues to follow the link to outer environment until it reaches the global environment.

Following diagram will give you an idea of how each environment is linked in your case.

enter image description here

P.S: What i explained above is something i learned from the @T.J Crowder's book. If you want to get into more details, I suggest you refer to the book as it is explained in detail in the book.

I know that the invocation of the function foo() returns both the function bar and the pointer to the variable a which is in its lexical scope.

It just returns one thing: the function bar that foo creates. The function bar, itself, has a reference to the environment where it was created, and thus to the a variable; it closes over that environment. So bar is a closure. All functions you create in JavaScript code are closures.

...can I say that I am assigning the variable func1 to the closure?

You can't assign anything to closures; it's the other way around. You can assign to variables (of various kinds) and you can initialize constants. What you're doing in const func1 = foo(); is initializing the constant func1 with the the function (you could say "closure" if you like) returned by foo.

Related