Js closure. Circuits in JavaScript: Practical example, features and rules

Hello everyone! In this article we will look at what is a closure in javascript.

This is a pretty simple topic, but it requires understanding. First, let's look at what happens inside the function.

Function Greeting (Name) (
// Lexicalenvironment \u003d (Name: "Nikolai", text: undefined)
var text \u003d "Hello," + Name;
// Lexicalenvironment \u003d (Name: "Nikolai", Text: "Hello, Nikolai")
Alert (text);
}

Greeting ("Nikolai");

What is happening here and what is Lexicalenvironment? Let's figure it out.

When the function is called, it creates an object LexicalenvironmentIn which all local variables and functions are recorded, as well as reference to the external scope (about this later). In our case, we have a local variable name.which immediately has a value (then that we pass) and this "Nikolai". In one of the articles I already wrote, however, I remind you that the interpretor knows everything about all variables in advance. It is about this that at the very beginning of the function already has a variable tEXT., the interpreter knows about it, but since we have not yet reached the assignment of this variable of some kind, it is equal to undefined.. Now we assign a variable value, and our object Lexicalenvironment Changes. His property tEXT. It becomes equal to the fact that we recorded ("Hello, Nikolai" in our case). After the function has been worked out, the object Lexicalenvironment Destroy. With subsequent calls, it will be created again, etc.

We now turn to the next example. Tell me what will be derived in this case?

Var b \u003d 2;
FUNCTION X (A) (
alert (a + b);
}
x (1);

Thought? I think most answered that the number 3 will be displayed, and this is the right answer, however you can tell you how the interpreter learned about the variable b.? After all, it is not in the body function. If not, let's understand.

Actually in javascript. there is a hidden property called [] . When the function is declared, it is always declared somewhere. This feature may be in another function, may be in a global object, etc. In our case, the function is declared in the global object. window., therefore, property x. [] \u003d Window.

Var b \u003d 2;
Function X (A) (// x. [] \u003d Window
// Lexicalenvironment \u003d (A: 1) -\u003e Window
alert (a + b);
}
x (1);

This arrow has an object Lexicalenvironment - This is a reference to the external scope, and this link is established by property. [] . So in the object Lexicalenvironment We will have a reference to an external object. window.. When the interpreter is looking for a variable, then he first searches for it in the object Lexicalenvironment, then, if he did not find a variable, then it looks in the link, goes into an external scope and searches for it there and so to the end. If he has not found this variable anywhere, it will be an error. In our case, variable a. The interpreter will take from the object Lexicalenvironment, and the variable b. From the object window.. Of course, if we have a local variable b. With some value, it will be recorded in the object Lexicalenvironment And subsequently will be taken from there, and not from the external field of visibility.

IMPORTANT! Remember that property [] It is installed by the place where the function was declared, and not caused, that is why the code below displays the number 3, and not 5, as some might think.

Bar B \u003d 2;
FUNCTION X (A) (
alert (a + b);
}

Function Y () (
var b \u003d 4;
x (1);
}

It was all a prelude only to understand how it all works, and it was easier for you to understand how the closures work. And now we turn directly to the topic of the article.

As I said, the object Lexicalenvironment Each time is destroyed each time after executing the function and is created again when re-calling. However, what if we want to save this data? Those. We want everything to be recorded in Lexicalenvironment Now, has been preserved and was used for the following challenges? It is for this that closure.

Function Greeting (Name) (
// LexicalenVironment \u003d (Name: "Nikolai")
RETURN FUNCTION () (// [] \u003d Lexicalenvironment
Alert (Name);
};
}

Var Func \u003d Greeting ("Nikolai");
greeting \u003d null;
FUNC ();

Let's see what we did. First we create a function greeting.in which the name is passed. The function creates an object Lexicalenvironmentwhere the property is created (our local variable) name. And she is assigned the name "Nikolai". And now important: we return another function from the function, inside which we derive through alert. variable name.. Further we assign a variable func. The value returned from the function greeting.And this value is our function that displays a name. now we greeting. We assign nULL. We just destroy our function greeting., however, when we call func.then we will see the value of the variable name.("Nikolai") functions greeting.. How is it possible to say you? And very simple. The thing is that our returned function also has a property. [] which refers to the external scope of visibility, and this external scope in our case is an object Lexicalenvironment Our function greeting.. Therefore, despite the fact that we delete our function greeting., an object Lexicalenvironment Not deleted and remained in memory, and it will remain in memory until it is at least one link. We have this link - our returned function that uses the variable name. of this facility Lexicalenvironment.

So, let's now give the definition of what is closure.

Circuit - Function with all variables that are available to it.

Well, the article turned out quite voluminous, but this is just because I tried to describe the whole process of work of the closure. To consolidate, I want to bring a simple example - a meter using the topic just studied. Please deal with the code and write in the comments, how and why it works. If you do not understand something, you can also ask a question. Thanks for attention!

FUNCTION MAKECOUNTER () (
var currentcount \u003d 0;

RETURN FUNCTION () (
CURRENTCOUNT ++;
Return CurrentCount;
};
}

VAR Counter \u003d MakeCounter ();
Counter ();
Counter ();
Alert (Counter ()); // 3.

IN JavaScript Functions Can be described not only one after another, but also one inside the other. When you have one function is inside another, the internal poundation has access to an alternating external function.

Function external (x) (var TMP \u003d 3; FUNCTION Internal (y) (Alert (X + Y + (++ TMP)); // Removes 16) internal (10);) external (2);

This code always gives 16, because the inner function sees x, which is a variable in the funkuction external. IN this case Argument function. Also internal () can see TMP from external ().

This is called closure or closure. If more precisely, the closure is called the external function, and everything inside it is called Closure Environment or closure environment.

Sometimes it is said that the closure is a function that returns the function, it is incorrectly, in order to name the function of the closure that the internal function applies to the variable from the outside of its scope.

FUNCTION FOO (X) (VAR TMP \u003d 3; RETURN FUNCTION (Y) (Alert (X + Y + (++ TMP)); // Will Also Alert 16)) VAR BAR \u003d FOO (2); // BAR IS NOW A Closure. BAR (10);

The above function will also display 16, since BAR even after Foo is completed continues to have access to X and TMP, even if the BAR variable itself is not inside the scope in which they were declared.

At the same time, since the TMP variable is still inside the BAR closure, it continues to increase each time BAR call.

Here the simplest example Circuit:

Var a \u003d 10; Function Test () (Console.log (A); // Conclusion 10 Console.Log (B); // Conclusion 6) VAR B \u003d 6; test ();

When you start a function in JavaScript, the environment is created for it, that is, a list of all the variable visible to it, not only the arguments and variables declared it within it, but also outside, in this example it is "a" and "b".

You can create more than one closure in one environment, returning them to an array, object or attaching to a global variable. In this case, they will all work with the same one X or TMP value without creating individual copies.

Since in our example X is the number, then its value copy In Foo as its argument x.

On the other hand, the JavaScript always uses links when objects are transmitted. If you called foo with an object as an argument, then the return closure would return the link to the original object!

FUNCTION FOO (X) (VAR TMP \u003d 3; RETURN FUNCTION (Y) (Alert (X + Y + TMP); x.memb \u003d x.memb? X.Memb + 1: 1; Alert (x.memb);) ) VAR AGE \u003d NUMBER (2); var Bar \u003d Foo (AGE); // BAR is now a closure referring to AGE. BAR (10);

As expected, each Call Bar (10) increases X.MEMB. What you might not expect, so that X continues to refer to the same object as AGE! After two calls BAR, Age.Memb will be equal to 2! By the way, the memory leaks in HTML objects occur.

In programming, closing or in the English-language version "Closing" is a method for implementing the contextual binding name in the first class functions. Operatively, it is an entry that stores the function along with the medium. The environment is a comparison of each free function with a value or reference called by closing JavaScript. It allows access to captured variables through copies of values \u200b\u200bor links, even when caused outside the region.

Concept of closures

Closings were developed in the 1960s for a mechanical assessment of expressions in calculation and applied in 1970 as a feature of the PAL programming language to support the first-class functions with the lexical sphere. Peter Landin defined the term "closure" in 1964 with the medium and control part used on the SECD machine to assess the lambda expressions associated with a lexical environment, which led to closing them or closure to JavaScript.

Such an explanation was included in 1975 as a lexically limited LISP version and was widespread. The lexical environment is a variety of valid variables in the program. It consists of an internal lexic medium and references to an external environment called nonlocal variables.

Lexic closures in JavaScript are features with its external environment. As in JavaScript, all variables have a link to type. JS uses only binding by reference - which corresponds to C ++ 11, and the lifetime of non-local variables captured by the function is distributed at the lifetime of the function.

Circuits in JavaScript usually appear in languages \u200b\u200bwith first-class values. Such languages \u200b\u200ballow you to transmit functions as arguments. And also come back from feature calls and attach to variable names. This happens like simple types, such as strings and integers.

In this example, Lambda expression (Lambda (\u003e \u003d (Book-Sales Book) Threshold) appears inside the BEST-SELLING-BOOKS function. When the lambda expression is calculated, the circuit creates a closure consisting of the code for the expression of the lambda and the reference to Threshold variable, which is a free variable within the lambda expression. The closure is then transmitted by Filter function that causes it repeatedly to determine which books should be added to the list of results and which should be discarded.

Since there is a closure in the value of Threshold, the latter can use it every time its Filter causes. Filter function itself can be defined in perfectly separate file. Here is the same example, rewritten in JS. It demonstrates how the closures under the hood in JavaScript work.

The keyword here is used instead of global FILTER function, but the rest of the structure and the effect of the code are the same. The function can create a closer and return it because it in this case is experiencing the execution of the function with variables F and DX continue to function after DERIVATIVE, even if the execution left their scope, and they are no longer visible.

In languages, without closing, the lifetime of the automatic local variable coincides with the execution of the stack frame, where this variable is declared. In languages \u200b\u200bwith JavaScript, the closures and functions of IIFE, variables must continue to exist until any existing locks have references to them. This is most often implemented using some shape of garbage collection.

The advantage of the closure is that it retains the scope, the "chain of visibility" of an external or "parental" context of execution. Such behavior can be used in several ways and has become a useful tool to prevent a variety of JavaScript errors. One of the most common is the problem of "loops."

The problem with the cycle occurs when the user creates a function in the cycle and expects the current value of the variable in this new functionEven if it changes in the context of cycles before calling a new function. The closures used in this way no longer have reference transparency and, therefore, are no longer clean functions, however, they are commonly used in unclean functional languages \u200b\u200bsuch as Scheme. In order to understand what is closing in JavaScript, you need to consider cases of use. In fact, in practice, they have many applications:

  1. They can be used to determine the control structures. For example, all standard Smalltalk management structures, including branches (IF / THEN / ELSE) and cycles (WHILE and FOR), are determined using objects whose methods take closures. Users can also easily use closures to determine the control structure. In the languages \u200b\u200bimplementing the purpose, you can create its multifunctional medium, allowing you to communicate confidentially and change this environment. The closure is used to implement object systems.
  2. Creating both private and public variable methods using module templates. Due to the fact that returned features inherit the area of \u200b\u200bthe parent function, they are available to all variables and arguments in this context.
  3. It is useful in a situation where the function uses the same resource for each call, but also creates a resource itself for it. This circumstance makes the method ineffective, which is eliminated exclusively by closing.

According to MDN (Mozilla Developer Network) "Closures are functions with independent variables that" remember "the environment of its creation." And, as a rule, when the function is completed, its local variables no longer exist. Understand how the closure in JavaScript works, you can consider several mechanisms. The first is a formal logic. For example, applying the Logname function, which takes one name as a parameter and registers it. Then I create the FOR cycle to go through the list of names, set the 1st timeout, and then call the LogName function passing in the current name.

In the first-class language, you can manipulate the same way as other types of data, such as int or string. Only this mechanism allows many to create incredible things, for example, to assign a variable function to subsequent call or transmit it as a parameter of another function.

This principle is used by many structures, as well as DOM events handlers. First, the event is "listening", then assign a callback function to be called every time the event is triggered.

Anonymous function is a function without a name. Practically novice programmers meet them daily, without understanding the game with numbers. For example, performing the addition operation, you can go through variables, for example:

  • var x \u003d 3;
  • y \u003d 5;
  • var z \u003d x + y.

Or if you do not intend to re-process numbers: var z \u003d 3 + 5;

These are anonymous rooms. For anonymous functions, you can declare them when they are used "on the fly" - without passing the variable. For example, take the function DO from previously:

(Alert ("CECI EST UNE FONCHAN ANONYME");

Moreover, there is an alternative syntax of the declaration of a function that emphasizes that both functions can be anonymous and refer to simple variables, which is a convenient way to install the callback function.

In fact, it is the same mechanism, but from this point of view it will allow you to see how the function is closed from the inside. As can be seen, since the functions are variables, like others, there is no reason for which they cannot be defined locally. In the zero order, such as C, C ++ and Java, all functions are determined at one level of visibility, in the same class or at the global level. On the other hand, in JavaScript, the local function disappears, as well as other local variables, as soon as the parent function ends, so it is not visible from other functions.

This is actually difficult, but JavaScript has a way to track the visibility of variables, and even in two ways. Assigning a global variable in JavaScript has the same mechanism as in Java - complex objects, arrays, DOM elements and others are transmitted by reference, so in the following code:

var tab \u003d; Var Tab2 \u003d Tab.

Where, Tab and TAB2 are two links to the same table, technically these are indicators controlled by the garbage collector. Functions are also transmitted by reference. The GlobalFN variable is no longer hidden. The order allows you to do what is demonstrated on the example of a JavaScript closure task.

This is how you can extract the function from the local context, if the function satisfies other local variables. A simple example: AUTO-INCREMENT, a function that returns an integer that increases by 1 each time call. Specifically, the INC function needs, which behaves as follows:

// RETOURNE 0 INC ();

// RETOURNE 1 INC ();

// RETOURNE 2 INC ();

With the closure it looks like:

fUNCTION MAKEINC () (VAR X \u003d 0; RETURN FUNCTION () (RETURN X ++;)) Var Inc \u003d makeInc ();

In the last row at the moment when the Inc variable is created, it carries some variables that are around, in this case x. It creates a certain invisible object around the function that contains this variable. This object is a JavaScript closure function. At the same time, each copy of the function will have its own closure:

var Inc1 \u003d makeInc ();

var Inc2 \u003d makeInc ();

As can be seen, the closure is very useful in many cases.

To avoid variable name conflicts, namespace are usually used. In JavaScript, namespaces are objects like any other.

Naturally, a.x and b.x is not the same variable. However, if you just need to start the script, without requiring saving variables for the rest, an anonymous function can be used as a closure. This gives a slightly strange syntax. Although the two codes in the middle are quite common, on the other hand, the function that is around is performed "on the fly". Pay attention to parentheses () at the end. And to be able to make a closure, anonymous function Itself must be surrounded by round brackets.

In this anonymous function use a local variable, paragraph. This is a great way to prevent name conflicts or clumsiness, but also against ataks XSS. Custom variables are protected, no one can change them to affect the behavior of the script.

There is an option: (Function () (// ...) ());

At the same time draw attention to the permutation of the brackets. The difference between these two options is quite difficult to explain because they are associated with how the code is read by a lexical analyzer. In both cases, the function is considered an expression, but this expression is not estimated simultaneously. Just need to remember that he takes two pairs of round brackets: one around the function and one behind it.

JavaScript programming in cycles

When the user performs large volumes of JavaScript programming, it is difficult for it to avoid cycles. Someone is crazy, after which they come to the idea that any implementation of JavaScript has a serious mistake. If the developer already has a cycle that he does not want to convert to use the function of the iterator, everything that he needs to do is a closure in which it defines new variables. They fix the current value of variables and varying on each iteration. The trick to capture variables is that the external closure is performed immediately during the current iteration of the cycle. You can use one of these two approximate approaches.

Now there is another simplified solution to this problem, since LET keyword is supported both in Firefox and in Chrome. It is keyword Instead of VAR variable block. LET works magically, because a new variable j is declared, the value of which value of which is fixed with the closure inside the cycle. However, it must be borne in mind that it does not continue to exist after the end of the same iteration of the cycle, since it is locally.

Loop and function

For a loop in JavaScript does not appear, as well as for a cycle in C or Java. In fact, it looks more like PHP. The most important knowledge about cycles in JS is that they do not create an area of \u200b\u200baction. JS does not have a block of sphere, only the function of volume. This property can be considered on the following fragment:

fUNCTION FOO () (VAR BAR \u003d 1;

for (var i \u003d 0; i< 42; i++) {var baz = i;} /* more code */}

It is clear that Bar is available in the entire function. Before the first iteration of the BAZ cycle will be undefined. After the cycle, it will have a value of 41 (and I will be 42). Thus, any variable declared anywhere in the function will be available everywhere in the function and will only be valid after it was appointed to him.

Shutters and aggregation

The closure is nothing more than functions, inside other functions, and are transmitted to some other context. They are called closure, as they close through local variables, that is, accessible to other areas of the sphere. For example, the time, x defined as the Foo parameter, and var bar \u003d foo (2) () will return 84.

Returned FOO function has access x. This is all important because it helps developers to create functions inside cycles depending on the cycle variables. Consider this fragment, which assigns Click processor to various elements:

// Elements IS An Array of 3 Dom Elements Var Values \u200b\u200b\u003d ["Foo", "Bar", "Baz"];

i.< l; i++) {var data = values[i];

elements [i] .onClick \u003d function () (Alert (DATA);

The value they will use alert when pressed, will be the same for everyone, namely BAZ. By that time, the event handler is called, for already completed. JS does not have a block area, i.e. All handlers use the link to the same DATA variable. After the loop, this value will be values. Each variable declaration creates one place in the storage memory. In for, this data is changed again and again, the position in memory remains unchanged.

Each event handler has access to the same position in memory. The only solution is to enter another area that "fixes" the current DATA value. JS has only a range of functions. Therefore, another function is entered. Example:

fUNCTION CREATEEVENTHANDLER (X) (RETURN FUNCTION () (ALERT (X);

for (var i \u003d 0, l \u003d elements.length;

i.< l; i++) {var data = values[i];

elements [i] .onClick \u003d CreateEventHandler (DATA);

It works, because the DATA value will be stored in the local area, CreateEventHandler and this function is performed on each iteration. It can be written in short, using the executable functions immediately:

for (var i \u003d 0, l \u003d elements.length;

i.< l; i++) {var data = values[i];

elements [i] .ONClick \u003d (Function (X) (FUNCTION () (Alert (x);

Practical example of closure in JavaScript

If the user does closure right above the code in the browser, it may encounter a problem, as it can make any syntax error. If it executes the code directly in the browser, the chances are very high not to compile the process of compiling WebPack. Possible solutions:

fUNCTION WORK (NAME) (

rETURN FUNCTION (TOPIC) (

console.log (What is $ (Topic) in $ (Name));

work ("JavaScript") ("Closure");

First, the function is called and the name argument is transmitted. Now this function of vocabulary also returns a function that also accepts the topics argument. This feature registers the output, and the output has access to the variable.

The insider functions area is not limited to this function, so the concept is called Closure, since it has access to this area external parameter. The returned function has access to the external lexical area or contexts. When the developer calls a function that also returns it, then first called variable function Always available for internal function. Further example with the following code.

An example of an internal function

Read more about the closure in JavaScript can be told on the second example. Now this fulfillment environment is destroyed, but the name of the parameter still exists. A new internal functional medium is created, which is an anonymous function. It has access to the area of \u200b\u200bthe outer lexical environment.

Thus, in a variable of the outside environment, it still exists in such a way that an anonymous function has access to the name variable prints in the console, for example, "what is a closure in JavaScript". Internal anonymous function //main.js

fUNCTION FACTORY () (VAR Products \u003d;

i ++) (Products.push (Function () (Console.log (I);

) Return Products;

) Var SOAP \u003d Factory ();

The result of this example is rather insignificant and equal to 2.

When soap is SOAP () called an external context variable, always 2, because in the cycle the condition is false in I<2, поэтому при этом значение i равно 2, а во время вызова нужно напечатать значение в консоль так, она всегда пишет 2. То же самое для мыла - soap ().

Creating functions "on the fly"

You can create a functions factory - FunctionFactory that performs custom tasks. The resulting function from the factory of functions will be a closure, storage medium of creating.

var functionFactory \u003d Function (Num1) (Return Num1 * Num2;

The above allows you to transfer one functionFactory number. Then functionfactory returns a closure, remembering the NUM1 value. The resulting function multiplies the original Num1 times the value of Num2, which is transmitted when called.

var Mult5 \u003d FunctionFactory (5);

var MULT10 \u003d FUNCTIONFACTORY (10);

The above simply creates the MULT5 and MULT10 functions. Now you can refer to any of these functions by passing a new number to multiply by 5 or 10. Now you can see the result.

The closure is one of the most powerful JavaScript functions, but it cannot be used correctly without understanding the essence. They are relatively easy to create by chance, this is how dangerous closures JavaScript. Their creation has potentially harmful effects, especially in some relatively common web browser environments. To avoid a random collision with disadvantages and take advantage of the advantages that they offer, it is necessary to understand their mechanism.

In this article, I will try to explain areas of visibility and closure in JavaScript, in which many experience difficulties.

Introduction

There are quite a few articles in the network that are trying to explain areas of visibility and closure, but in general, I would say that most of them are not entirely understandable. In addition, in some articles it is assumed that you are programmed before 15 other languages, although I think most of the people writing on JavaScript have only experience in HTML and CSS, and not in C or Java.

Consequently, the purpose of this article is to explain for all - what is the scope of visibility and the closure, as they work, and most importantly what their advantage. Before reading this article, you need to know the basic concepts about variables and functions in JavaScript.

Area of \u200b\u200bvisibility

Scope means where variables and functions are available, and in which context they are executed. A variable or function can be defined in a global or local area of \u200b\u200bvisibility. Variables have the so-called function of function visibility, and functions have the same scope as variables.

Global scope

When something is global, it means that it is available from anywhere in your code. Consider an example:

var monkey \u003d "gorilla"; Function Greetvisitor () (Return Alert ("Hello Dear Blog Reader!");)

If this code was performed in a web browser, then the visibility area would be window, theover it will be available for everything that is executed in the Window.

Local scope

In contrast to the global visibility area, the local visibility area is when something is defined and available only in some part of the code, such as a function. Consider an example:

function Talkdirty () (VAR Saying \u003d "Oh, You Little VB Lover, You"; Return Alert (Saying);) Alert (Saying); // Thrown An Error

In this example, the Saying variable is available only inside the Talkdirty function, outside which it is not defined. Note: If you were identified by Saying without a VAR keyword, it would automatically become global.

In addition, if you have nested functions, the internal function will have access to the functions in which it is embedded, as well as variables:

function CapitalIZENAME (RETURN FIRSTNAME.TUPPERCASE ();) var Capitalized \u003d CapitalIZENAME (); Return Capitalized;) Alert (Savename ("Robert")); // RETURNS "ROBERT"

As you just saw, the internal function Capitalizename does not need to transmit any parameters, because It has full access to the FIRStname parameter in the external function of the Savename. For greater clarity, consider another example:

function Siblings () (VAR Siblings \u003d ["john", "liza", "peter"]; function siblingcount () (var siblingslength \u003d siblings.length; Return Siblingslength;) Function JoinsiblingNames () (Return "I Have" + SiblingCount () + "Siblings: Nn" + siblings.join ("n");) Return joinsiblingnames ();) alert (siblings ()); // Outputs "I Have 3 Siblings: John Liza Peter"

As you can see, both internal functions have access to the SIBLINGS array, and each internal function has access to another internal function of the same level (in this case, JoinsiblingNames has access to SiblingCount). However, the SIBLINGSLENGTH variable inside SIBLINGCOUNT is only available inside this function, i.e. In this area of \u200b\u200bvisibility.

Circuit

Now that you have a clearer idea of \u200b\u200bvisibility areas, we will add closure to them. Circuits are expressions, usually functions that can work with a set of variables within a certain context. Or, simpler words, internal functions that refer to local variables of external functions form closures. For example:

fUNCTION Add (x) (Return X + Y;);) var Add5 \u003d Add (5); var no8 \u003d add5 (3); Alert (NO8); // Returns 8.

Blimey! What's going on here? Let's figure out:

1. When we call the ADD function, it returns the function.

2. This function closes the context and memorizes how the parameter X is at this time (i.e., in this case, the value 5)

3. When the result of the Add function is assigned to the ADD5 variable, it will always know what X was when creating this variable.

4. The variable ADD5 refers to a function that will always add value 5 to any argument transmitted to it.

5. This means that when we call ADD5 with the value 3, it will fold the number 5 and 3, and will return 8.

In fact, in the JavaScript world, the ADD5 function looks like this:

fUNCTION ADD5 (Y) (RETURN 5 + Y;)

The notorious problem of cycles
How many times did you create cycles in which you wanted to assign a value of I in any way, for example, an element, and understood that only the last value I was returned?

Wrongappeal

Let's look at this incorrect code that creates 5 elements , adds the value i as the text to each element and onclick, which is expected to produce alert with the value I for this reference, i.e. The same value as in the text of the element. Then the elements are added to Document Body:

<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function () { alert(i); }; document.body.appendChild(link); } } window.onload = addLinks;

Each element contains the correct text, i.e. "Link 0", "Link 1", etc. But whatever the link you clicked, it shows alert with a number 5. What is the matter? The reason is that the value of the variable i increases by 1 with each iteration of the cycle, and because ONCLICK event is not executed, but simply applies to the element The value increases.

Therefore, the cycle continues to work until i becomes equal to 5, which is the last value before going out of the AddLinks function. Further, every time the ONClick event is triggered, the last value I is taken.

Proper appeal

What you need to do is create a closure. As a result, when you apply the value I to an OnClick Event Event , I will be assigned the value of I at that time. For example, like this:

function AddLinks () (for (Var i \u003d 0, Link; I<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function (num) { return function () { alert(num); }; }(i); document.body.appendChild(link); } } window.onload = addLinks;

Using this code, if you click on the first element, Alert will issue "0", on the second - "1", etc. The solution is that the internal function applied to the ONCLICK event creates a closure in which the NUM parameter appeals, i.e. to the value of i at that time.

This feature "remembers" the desired value, and can then return the corresponding digit when the OnClick event is triggered.

Secure-executing functions

Safe-executing functions are such functions that begin to execute immediately and create their closure. Consider an example:

(FUNCTION () (VAR DOG \u003d "GERMAN SHEPHERD"; Alert (DOG);)) (); Alert (DOG); // Returns undefined.

So, the DOG variable is available only within this context. Think, hidden variable Dog ... But, my friends, the most interesting thing begins with this! It solved our problem with a cycle, and it is also the basis for Yahoo JavaScript Module Pattern.

Yahoo JavaScript Module Pattern

The essence of this pattern is that it uses a safe-executable function to create a closure, therefore it makes it possible to use Private and Public properties and methods. Simple example:

var person \u003d function () (// Private var name \u003d "robert"; return (getName: Function () (Return Name), SetName: Function (NewName) (Name \u003d NewName;));) (); alert (person.name); // undefined alert (person.getname ()); // "Robert" person.setname ("Robert Nyman"); alert (person.getname ()); // "Robert Nyman"

The advantage of this approach is that you can define yourself, which will be open in your object (and can be changed), and that closed, which no one can contact or change. The Name variable is hidden outside the context of the function, but is accessible to the GETNAME and SETNAME functions, because They create closures in which there is a link to the name variable.

Conclusion

I sincerely hope that after reading this article, newcomers and experienced programmers received a clearer idea of \u200b\u200bhow in JavaScript work areas of visibility and closures. Questions and reviews are welcome, and if you have something important to let something, then I can update the article.

Good coding!

Circuits in JavaScript Used to hide variable values \u200b\u200band store functions. The point is that when closed, one function is created in which the variables are specified and which as a result of its operation returns its nested function. Then, in it (in the main function), an embedded function is created, in which some operations are made with variable function variables and which returns the result of these operations. Next, the main function is equal to a variable - this variable can be called out how much time and however, the values \u200b\u200bof the variables of the main function will be stored and updated. She is "closed."

As you know, in JavaScript the field of visibility of local variables (declared VAR word) It is the body of the function within which they are defined.

If you declare a function inside another function, the first gets access to variables and arguments of the latter:

Code: Function Outerfn (Myarg) (
Var MyVar;
FUNCTION INNERFN () (
// has access to MyVar and Myarg
}
}

At the same time, such variables continue to exist and remain available internal function even after the external function in which they are defined was executed.

Consider an example - a function that returns the number of eigenvalues:

Code: FUNCTION CREATECOUNTER () (
var numberofcalls \u003d 0;
RETURN FUNCTION () (
RETURN ++ NumberOfcalls;
}
}
vAR FN \u003d CreateCounter ();
fn (); //one
fn (); // 2.
fn (); // 3.

In this example, the function returned by CreateCounter uses the NumberOfcalls variable, which saves the desired value between its calls (instead of immediately stopping its existence with the CreateCounter return).

It is for these properties that such "nested" functions in JavaScript are called closures (the term who came from programming functional languages) - they "closer" the variables and arguments of the function within which are defined.

Application of closures

Simplifies a little example above - remove the need to separately call the CreateCounter function, making it annexic and calling it immediately after its ad:

Code: var fn \u003d (function () (
var numberofcalls \u003d 0;
RETURN FUNCTION () (
RETURN ++ NumberOfcalls;
}
})();

Such a design allowed us to bind data to the function, which remained between its challenges is one of the uses of closures. In other words, with the help of them we can create functions that have a variable state.

Other good use of closures - the creation of functions, in turn, also creating functions - what some would be called the T.N. MetaProgramming.
For example:

Code: Var CreateHellofunction \u003d FUNCTION (NAME) (
RETURN FUNCTION () (
Alert ("Hello," + Name);
}
}
var Sayhellohabrahabr \u003d CreateHellofunction ("Habrahabr");
sayhellohabrahabr (); // Alerts "Hello, Habrahabr"

Thanks to the closure, the returned function "remembers" the parameters transferred to the functions of creating that we need for this kind of things.

A similar situation occurs when we do not return an internal function, and hang on any event - since the event arises after the function has been fulfilled, the closure again helps not lose the data transmitted when the data processer is created.

Consider a slightly more complex example - a method that ties the function to a specific context (i.e., the object to which this word will indicate in it).

Code: Function.prototype.Bind \u003d FUNCTION (CONTEXT) (
var fn \u003d this;
RETURN FUNCTION () (
RETURN FN.APPLY (Context, Arguments);
};
}
var Hellopage \u003d (
Name: "habrahabr",
init: function () (
Alert ("Hello," + this.name);
}
}
//Window.Onload \u003d Hellopage.init; // Alertnul would undefined, because This indicates the Window
window.onload \u003d Hellopage.init.bind (Hellopage); // now everything works

In this example, with the help of a closure, a function, triggered Bind "Ohm, remembers the initial function and the context assigned to it.

Next, fundamentally different use of closures - data protection (encapsulation). Consider the following design:

Code: (Function () (

})();

Obviously, inside the closure we have access to all external data, but it has its own. Due to this, we can surround part of the code like a design in order to close the local variables from access outside. (One example of its use can be seen in the source code of the jQuery library, which surrounds the closure of all its code so as not to output the variables only to it).

There is, however, one associated with such use trap - the meaning of the word this is lost inside the closure. It is solved as follows:

Code: (Function () (
// Highest this will continue
)). Call (this);

Consider another reception from the same series. It was widely popularized by his developers of the Yahoo Ui framework, calling him "Module Pattern" and writing a whole article on it in an official blog.
Let us have an object (Singleton) containing any methods and properties:

Code: var MYMODULE \u003d (
Name: "habrahabr",
SayPreved: Function (Name) (
Alert ("Preved" + name.touppercase ())
},
this.sayPreved (this.name);
}
}
MyModule.sayPrevedTohabrahabr ();

With the help of closure, we can make methods and properties that are not used outside the object, private (i.e. available only to him):

Code: var mymodule \u003d (function () (
VAR NAME \u003d "Habrahabr";
Function SayPreved () (
Alert ("Preved" + name.touppercase ());
}
Return (
SayPrevedTohabrahabr: Function () (
SayPreved (Name);
}
}
})();
MyModule.sayPrevedTohabrahabr (); // Alerts "Preved Habrahabr"

Finally, I want to describe a common mistake that many rides into a stupor in case of ignorance of how closures work.

Let us have an array of links, and our task is to make it so that when you click on each allert, its sequence number is displayed.
The first decision that comes to mind looks like this:

Code: for (var i \u003d 0; i< links.length; i++) {
Alert (I);
}
}

In fact, it turns out that when you click on any link, the same number is displayed - the value of Links.Length. Why is this happening? In connection with the closure, the announced auxiliary variable I continues to exist, with and at the moment when we click on the link. Since by that time the cycle has already passed, I remains equal to the number of links - this value we are visible when clicking.

This problem is solved as follows:

Code: for (var i \u003d 0; i< links.length; i++) {
(FUNCTION (I) (
Links [i] .ONClick \u003d function () (
Alert (I);
}
)) (i);
}

Here, with the help of another closure, we "shadow" variable I, creating it a copy in its local area of \u200b\u200bvisibility at each cycle step. Thanks to this, everything works now as conceived.

That's all. This article, of course, does not claim to be exhaustive, but someone, I hope, still helps to figure it out.

zy.
For saving between calls easier to use func_name.attr type:

Code: FUNCTION COUNTIT (RESET) (
if (RESET ||! Countit.cnt) Countit.cnt \u003d 0;
rETURN COUNTIT.CNT ++;