JavaScript Shortcuts: Case Study, Features, and Rules

In programming, closure or in the English version of “closure” is a method for implementing the contextual name of binding in the language of functions of the first class. Operationally, it is a record storing a function along with the environment. An environment is a mapping of each free function to a value or reference by name created by a closure in Javascript. It allows access to captured variables through copies of values ​​or references, even when called out of scope.

Closure concept

Closures in javascript practice




Closures were developed in the 1960s for the mechanical evaluation of calculus expressions and applied in 1970 as a feature of the PAL programming language to support first-class functions with the lexical sphere. Peter Landin defined the term “closure” in 1964 with the environment and control used on the SECD machine to evaluate lambda expressions associated with the lexical environment, which led to their closure or closure in Javascript.

This explanation came in 1975 as a lexically limited version of LISP and became widespread. The lexical environment is the set of valid variables in the program. It consists of an internal lexical environment and references to an external environment called nonlocal variables.





Javascript lexical closures are functions with its external environment. Like JavaScript, all variables have a type reference. JS uses only reference binding - which corresponds to C ++ 11, and the lifetime of non-local variables captured by the function extends to the lifetime of the function.

Practical example




First-class features

Javascript closures usually appear in languages ​​with first-class meanings. Such languages ​​allow you to pass functions as arguments. And also return from function calls and bind to variable names. This happens like simple types such as strings and integers.

First-class features




In this example, the expression lambda (lambda (book) (> = (book-sales book) threshold)) appears inside the best-selling-books function. When a lambda expression is evaluated, the circuit creates a closure consisting of code for the lambda expression and a reference to the threshold variable, which is a free variable inside the lambda expression. The closure is then passed to the filter function, which calls 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 threshold value, the latter can use it every time its filter calls. The filter function itself can be defined in a completely separate file. Here is the same example rewritten in JS. It demonstrates how closures under the hood work in Javascript.

Closures under the hood in Javascript




The keyword is used here instead of the global filter function, but otherwise the structure and effect of the code are the same. A function can create a closure and return it, since in this case it survives the execution of the function with the 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 closures, the lifetime of an automatic local variable coincides with the execution of the stack frame where this variable is declared. In languages ​​with Javascript closures and iife functions, variables must continue to exist as long as any existing locks have references to them. This is most often implemented using some form of garbage collection.

Areas of use

Areas of use




The advantage of a closure is that it preserves the scope, the "chain of visibility" of the external or "parent" execution context. This behavior can be used in several ways and has become a useful way to prevent a range of JavaScript errors. One of the most common is the loop problem.

A loop problem occurs when the user creates a function in a loop and expects the current value of the variable to remain in this new function, even if it changes in the context of loops before calling the new function. Closures used in this way no longer have referential transparency and therefore are no longer pure functions, however, they are commonly used in impure functional languages ​​such as Scheme. In order to understand what a closure is in Javascript, you need to consider cases of their use. In fact, they have many uses in practice:

  1. They can be used to define management structures. For example, all standard Smalltalk control structures, including branches (if / then / else) and loops (while and for), are defined using objects whose methods take closures. Users can also easily use closures to define control structures. In languages ​​that implement the purpose, you can create a multifunctional environment, allowing you to communicate privately and change this environment. Closure is used to implement object systems.
  2. Creating both private and public variable methods using module templates. Due to the fact that the returned functions inherit the scope of the parent function, they are accessible to all variables and arguments in this context.
  3. It is useful in situations where the function uses the same resource for each call, but also creates the resource itself for it. This circumstance makes the method ineffective, which is eliminated exclusively by closure.

JavaScript functionality

JavaScript functionality




According to the MDN (Mozilla Developer Network), "Closures are functions with independent variables that" remember "their creation environment." And, as a rule, when a function completes, its local variables no longer exist. To understand how closure in Javascript works, consider several mechanisms. The first is formal logic. For example, using the function logName, which takes one name as a parameter and registers it. Then I create a for loop to iterate over the list of names, set the 1st timeout, and then call the logName function, passing in the current name.

In a first-class language, functions can be manipulated in the same way as other data types, such as int or string. Only this mechanism allows many to create incredible things, for example, assign a function to a variable for its subsequent call or pass it as a parameter to another function.

Parameter of another function




This principle is used by many structures, as well as DOM event handlers. First they “listen” to the event, then they assign a callback function that will be called each time the event is triggered.

First they “listen” to the event




Anonymous Functions

Anonymous Functions




An anonymous function is a function without a name. Almost novice programmers meet them every day, not understanding the game with numbers. For example, performing the add operation, you can go through variables, for example:

  • var x = 3;
  • y = 5;
  • var z = x + y.

Or if you do not intend to reprocess the numbers: var z = 3 + 5;

These are anonymous numbers. For anonymous functions, you can declare them when they are used on the fly - without passing a variable. For example, take the do function from earlier:

do (function ()

{alert ("Ceci est une fonction anonyme.");

}

);

Moreover, there is an alternative syntax for declaring a function, which emphasizes that at the same time functions can be anonymous and refer to simple variables, which is a convenient way to set a callback function.

Function Definition

Actually, this is the same mechanism, but from this point of view, it will allow you to see how the closure of a function occurs from the inside. As you can see, since functions are variables, like others, there is no reason why they cannot be defined locally. In a zero-order language such as C, C ++, and Java, all functions are defined at the same level of visibility, in the same class, or globally. In JavaScript, on the other hand, a local function disappears, like other local variables, as soon as the parent function ends, so it is not visible from other functions.

Function Definition




This is actually complicated, 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 passed by reference, therefore, in the following code:

var tab = [51, 42, 69]; var tab2 = tab.

Where, tab and tab2 are two references to the same table, technically these are pointers controlled by the garbage collector. Functions are also passed by reference. The globalFn variable is no longer hidden. The order allows you to do this, as demonstrated by the example of the Javascript closure task.

GlobalFn variable




Here's how to extract a function from the local context if the function satisfies other local variables. A simple example: auto-increment, a function that returns an integer that increments by 1 each time it is called. Specifically, we need the inc function, which behaves as follows:

inc ();

// retourne 0 inc ();

// retourne 1 inc ();

// retourne 2 inc ();

// retourne 3

// etc.

With a closure, it looks:

function makeInc () {var x = 0; return function () {return x ++; }} var inc = makeInc ();

In the last line at the moment the inc function variable is created, it carries some kind of variables that are around, in this case x. It creates an invisible object around a function that contains this variable. This object is a Javascript closure function. In addition, each copy of the function will have its own closure:

var inc1 = makeInc ();

var inc2 = makeInc ();

inc1 ();

// 0 inc1 ();

// 1 inc1 ();

// 2 inc2 ();

// 0 inc1 ();

// 3 inc2 ();

// 1 inc2 ();

// 2

As you can see, closure is very useful in many cases.

Variable Name Conflicts

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

Variable Name Conflicts




Naturally, Ax and Bx are not the same variable. However, if you just need to run the script without requiring saving variables for the rest, you can use an anonymous function, like a closure. This gives a somewhat strange syntax. Although the two lines of code in the middle are pretty common, on the other hand, the function that is around is executed on the fly. Pay attention to the parentheses () at the end. And in order to be able to make a closure, the anonymous function itself must be surrounded by parentheses.

This anonymous function uses a local variable, paragraph. This is a great way to prevent name clashes or clumsiness, but also against XSS attacks, user variables are protected, no one can change them to affect script behavior.

There is an option: (function () {// ...} ());

At the same time pay attention to the rearrangement of brackets. The difference between these two options is quite difficult to explain, since they are related to how the code is read by the lexical analyzer. In both cases, the function is considered an expression, but this expression is not evaluated at the same time. You just need to remember that it takes two pairs of parentheses: one around the function and one after it.

Javascript programming in loops

When a user performs large amounts of Javascript programming, it is difficult for him to avoid loops. This is driving someone crazy, after which they come to the conclusion that any implementation of Javascript has a serious error. If the developer already has a loop that he does not want to convert in order to use the iterator function, all he needs to do is a closure in which he defines new variables. They fix the current value of the variables, and changing at each iteration. The trick to capturing variables is that an external closure is executed immediately during the current loop iteration. You can use one of these two sample approaches.

Cycle Programming




Now there is another simplified solution to this problem, since let keyword is supported in both Firefox and Chrome. It is a keyword instead of a var variable block. Let works magically, because a new variable j is declared, the value of i of which is fixed by a closure inside the loop. However, it should be borne in mind that it does not continue to exist after the end of one iteration of the cycle, since it is local.

Loop and function

The For loop in JavaScript does not seem to be the same as the for loop in C or Java. Actually it is more like PHP. The most important knowledge about loops in JS is that they do not create scope. JS does not have a sphere block, only a volume function. This property can be seen in the following snippet:

function foo () {var bar = 1;

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

It is clear that bar is available in the whole function. Until the first iteration of the loop, baz will be undefined. After the loop, 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 have a value only after it has been assigned to it.

Gates and Aggregation

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

The returned function foo has access x. This is all important because it helps developers create functions within loops that depend on loop variables. Consider this snippet that assigns a click handler to various elements:

// elements is an array of 3 DOM elements var values ​​= ['foo', 'bar', 'baz'];

for (var i = 0, l = elements.length;

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

elements [i] .onclick = function () {alert (data);

};

}

The value that they will use alert when clicked will be the same for everyone, namely baz. By then, the event handler is called, for has already completed. JS does not have a block area, i.e. all handlers use a link to the same data variable. After the loop, this value will be values. Each variable declaration creates one place in the data storage memory. In for, this data changes over and over, the position in memory remains unchanged.

Each event handler has access to the same position in memory. The only solution is to introduce another area that “fixes” the current value of data. JS has only a function area. Therefore, another function is introduced. Example:

function createEventHandler (x) {return function () {alert (x);

}

}

for (var i = 0, l = elements.length;

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

elements [i] .onclick = createEventHandler (data);

}

This works because the data value will be stored in the local scope, createEventHandler, and this function is executed at each iteration. This can be written shorter using immediately executable functions:

for (var i = 0, l = elements.length;

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

elements [i] .onclick = (function (x) {function () {alert (x);

};

}

(data));

}

Practical javascript closure example

If the user locks directly above the code in the browser, he may encounter a problem, as he can make any syntax error. If it executes the code directly in the browser, then the chances are very high so as not to compile the webpack compilation process. Possible solutions:

//main.js

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 passed. Now this vocabulary function also returns a function that also takes a topic argument. This function registers the output, and the output has access to the variable.

The scope of Insider functions is not limited to this function, therefore the concept is called Closure, since it has access to this area of ​​an external parameter. The returned function has access to the outer lexical region or contexts. When a developer calls a function that also returns it, then the first called function variables are always available for the internal function. The following is an example with the following code.

Example with the following code




Example internal function

You can tell more about closure in Javascript in the second example. Now this runtime is being destroyed, but the parameter name still exists. A new internal functional environment is created, which is an anonymous function. She has access to the area of ​​the external lexical environment.

Thus, in the environment variable, it still exists so that an anonymous function with access to the name variable prints to the console, for example, “What is a closure in Javascript”. Internal anonymous function //main.js

function factory () {var products = [];

for (var i = 0;

i <2;

i ++) {products.push (function () {console.log (i);

});

} return products;

} var soap = factory ();

soap [0] ();

soap [1] ();

The result of this example is quite negligible and equals 2.

When soap - soap [0] () is called an external context variable, always 2, because in the loop the condition is false at i <2, therefore the value of i is 2, and during the call you need to print the value to the console like this, it always writes 2. - soap [1] ().

« »

- functionFactory, . , .

var functionFactory = function(num1) {return function(num2) {return num1 * num2;

}

}

functionFactory. functionFactory , num1. num1 num2, .

var mult5 = functionFactory(5);

var mult10 = functionFactory(10);

mult5 mult10. , , 5 10. .

> mult5(3)

15

> mult5(5)

25

> mult10(3)

thirty

> mult10(5)

fifty

Closing 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 accident, which is the danger of Javascript closures. Creating them has potentially harmful consequences, especially in some relatively common web browser environments. In order to avoid an accidental encounter with disadvantages and take advantage of the advantages they offer, it is necessary to understand their mechanism.




All Articles