Technically, how do JavaScript closures work?

How do JavaScript locks work?

JavaScript locks for beginners

Submitted by Morris on Tue, 2006-02-21 10:19. Edited by the community since.

Closures are not magic

This page explains closures so that a programmer can understand them - using working JavaScript code. It is not for gurus or working programmers.

Degrees are Not hard to be understood as soon as the core concept is clarified. However, they are impossible to understand from reading theoretical or academically oriented explanations!

This article is for programmers with programming experience in a standard language who can read the following JavaScript function:

Two brief summaries

  • When a function () declares other functions (bar and baz), the family is the local variables created in not destroyed when the function is terminated. The variables only become invisible to the outside world. can therefore return the functions and cleverly and you can continue to read, write and communicate with each other via this closed family of variables ("the closure"). With whom nobody can interfere, not even someone who will call again in the future.

  • A degree is an opportunity to support top-notch features; It is an expression that can reference variables in its scope (when it was first declared), assigned to a variable, passed as an argument to a function, or returned as a function result.

An example of a degree

The following code returns a reference to a function:

Most JavaScript programmers will understand how to return a reference to a function to a variable () in the code above. If you don't, you will need to look at this before you can study degrees. A programmer using C would think of the function as returning a pointer to a function, and that the variables and are each a pointer to a function.

There is a critical difference between a C pointer to a function and a JavaScript reference to a function. In JavaScript, you can think of a function reference variable as both a pointer to a function as well as as a hidden pointer to a conclusion.

The above code is closed because the anonymous function is being used as a within Another function is declared, in this example. When you use the keyword in another function in JavaScript, you create a closure.

In C and most other common languages ​​there to a function back, all local variables can no longer be accessed because the stack frame is destroyed.

If you declare a function within another function in JavaScript, the local variables of the outer function can remain accessible after the return from this function. This is shown above because we are calling the function after returning from. Notice that the code we called references the variable that a local variable the function was.

We can see from the output of that the code is referencing the variable. The anonymous function can refer to the one that contains the value because the local variables were kept alive by in a closure.

The genius is that in JavaScript, a function reference also has a secret reference to the closure it was created in - much like delegates are a method pointer plus a secret reference to an object.

More examples

For some reason, closures seem really hard to understand when you read about them, but when you see some examples it becomes clear how they work (it took a while). I recommend working through the examples carefully until you understand how they work. If you started using closures without fully understanding how they work, you would be creating some very strange errors soon!

Example 3

This example shows that the local variables are not copied - they are kept for reference. It is as if the stack frame is retained in memory even after the external function has ended!

Example 4

All three global functions have a common reference to the conclusion same because they are all declared in a single call to.

The three functions share access to the same termination - the local variables of when the three functions were defined.

Note that in the example above, when you call again, a new termination (stack frame!) Is created. The old variables,, are used with the functions new overwritten that have the new degree. (If you declare a function in another function in JavaScript, the inner functions are recreated every time when the outer function is called.)

Example 5

This example shows that the termination contains all local variables that were declared in the outer function before the termination. Note that the variable is actually declared after the anonymous function. The anonymous function is declared first and when this function is called it can access the variable as it is in the same scope (JavaScript does variable lift). Also, it just calls directly the function reference returned by - it's exactly the same as before, but without the temporary variable.

Tricky: Note that the variable is also located inside the closure and can be called from any other function that has been declared in, or that it can be accessed recursively from within the inside function.

Example 6

This is a real problem for a lot of people so you need to understand it. Be very careful when defining a function inside a loop: the local variables from the closure may not behave as you might first think.

You need to understand the variable lifting function in Javascript to understand this example.

The line adds a reference to an anonymous function three times to the result array. If you are not that familiar with anonymous features, keep these things in mind:

Note that there are three logs when running the example! This is because, just like in the previous examples, there is only one termination for the local variables for (which,, and are). . When the anonymous functions on the line are called; They all use the same single deal and use the current value for and within that one deal (where has value because the loop had completed, and has value). Notice that we are indexing from 0, hence has the value. And the i ++ increases in value.

It can be helpful to see what happens when a declaration of the variables at block level (via the keyword) is used instead of a declaration of function-related variables via the keyword. When this change is made, each anonymous function in the array has its own closure. When the example is run, the output looks like this:

If the variable is also defined with instead of, the output is:

Example 7

In this last example, a separate closure is created each time the main function is called.

Summary

When everything seems completely unclear, it is best to play with the examples. Reading an explanation is much more difficult than understanding examples. My explanations about closures, stacking frames, etc. are technically incorrect - they are gross simplifications to make it easier to understand. Once the basic idea is clarified, you can pick up the details later.

Closing points:

  • Whenever you use in another function, a closure is used.
  • Whenever you use in a function, a closure is used. The text you can refer to function local variables and you can even create new local variables by using in.
  • If you use (the function constructor) in a function, no closure is created. (The new function cannot reference the local variables of the outer function.)
  • Closing in JavaScript is like keeping a copy of all local variables, just like exiting a function.
  • It is probably best to think that a closure is only ever made one entry on a function and the local variables are added to that closure.
  • Each time a function is called with a closure, a new set of local variables is retained (provided the function contains a function declaration and either a reference to that internal function is returned or an external reference is retained for it in some way).
  • Two functions may look like they have the same source code, but because of their “hidden” closure, they behave completely differently. I don't think JavaScript code can actually figure out whether a function reference has a closure or not.
  • If you try to make dynamic source code changes (for example :) it won't work if there is a closure (of course you would never think of creating source code strings for substitution at runtime, but ...).
  • It is possible to get function declarations within function declarations within functions ... and you can get closings at more than one level.
  • I think usually a degree is a term for both the function and the variables that are being recorded. Note that I am not using that definition in this article!
  • I suspect that the closures in JavaScript are different from those normally found in functional languages.

Left

Many Thanks

If you just Having studied degrees (here or elsewhere!), I am interested in any feedback from you on any changes you may suggest to make this article clearer. Send an email to morrisjohns.com (morris_closure @). Please note that I am not a guru when it comes to JavaScript - and neither is it when it comes to closures.


The original article by Morris is in the Internet Archive.