Learn more about closures in JavaScript. JavaScript Closures Creating Closures in a Loop: A Very Common Mistake

Closures in javascript are used to hide variable values ​​and store function values. The point is that when closing, one function is created in which variables are set and which, as a result of its work, returns its nested function. Then a nested function is created in it (in the main function), in which some operations are performed with the variables of the main function and which returns the result of these operations. Next, the main function is equated to some variable - this variable can be called as many times as desired and at the same time the values ​​of the variables of the main function will be stored and updated in it. she is "closed".

As you know, in JavaScript the scope of local variables (declared by the word var) is the body of the function within which they are defined.

If you declare a function inside another function, the former has access to the latter's variables and arguments:

Code: function outerFn(myArg) (
var myVar;
function innerFn() (
//has access to myVar and myArg
}
}

Moreover, such variables continue to exist and remain accessible to the internal function even after the external function in which they are defined has been executed.

Let's look at an example - a function that returns the number of its own calls:

Code: function createCounter() (
var numberOfCalls = 0;
return function() (
return ++numberOfCalls;
}
}
var fn = createCounter();
fn(); //1
fn(); //2
fn(); //3

In this example, the function returned by createCounter uses the numberOfCalls variable, which retains the desired value between calls (instead of immediately terminating when createCounter returns).

It is for these properties that such “nested” functions in JavaScript are called closures (a term that comes from functional programming languages) - they “close” the variables and arguments of the function within which they are defined.

Applying Closures

Let's simplify the example above a little - remove the need to separately call the createCounter function, making it anonymous and calling it immediately after its declaration:

Code: var fn = (function() (
var numberOfCalls = 0;
return function() (
return ++ numberOfCalls;
}
})();

This design allowed us to bind data to a function that persists between its calls - this is one of the uses of closures. In other words, with the help of them we can create functions that have their own mutable state.

Another good use of closures is to create functions that in turn also create functions - what some would call the so-called technique. metaprogramming.
For example:

Code: var createHelloFunction = function(name) (
return function() (
alert("Hello, " + name);
}
}
var sayHelloHabrahabr = createHelloFunction("Habrahabr");
sayHelloHabrahabr(); //alerts "Hello, Habrahabr"

Thanks to the closure, the returned function “remembers” the parameters passed to the creating function, which is what we need for this kind of thing.

A similar situation arises when we do not return an internal function, but hang it on some event - since the event occurs after the function has been executed, the closure again helps not to lose the data passed when creating the handler.

Let's look at a slightly more complex example - a method that binds a function to a specific context (i.e. the object to which the word this will point in it).

Code: Function.prototype.bind = function(context) (
var fn = this;
return function() (
return fn.apply(context, arguments);
};
}
var HelloPage = (
name: "Habrahabr",
init: function() (
alert("Hello, " + this.name);
}
}
//window.onload = HelloPage.init; //alert undefined, because this would point to window
window.onload = HelloPage.init.bind(HelloPage); //now everything works

In this example, using closures, the function returned by bind remembers the initial function and the context assigned to it.

The next, fundamentally different application of closures is data protection (encapsulation). Consider the following construction:

Code: (function() (

})();

Obviously, inside the closure we have access to all external data, but at the same time it also has its own. Thanks to this, we can surround parts of the code with a similar construction in order to close the local variables that are inside from access from the outside. (You can see one example of its use in the source code of the jQuery library, which surrounds all its code with a closure so as not to expose variables only it needs outside of it).

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

Code: (function() (
//higher this will be preserved
)).call(this);

Let's look at another technique from the same series. The developers of the Yahoo UI framework popularized it everywhere, calling it “Module Pattern” and writing an entire article about it on the official blog.
Suppose we have an object (singleton) containing some methods and properties:

Code: var MyModule = (
name: "Habrahabr",
sayPreved: function(name) (
alert("PREVED " + name.toUpperCase())
},
this.sayPreved(this.name);
}
}
MyModule.sayPrevedToHabrahabr();

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

Code: var MyModule = (function() (
var name = "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 drives many people into a stupor if they do not know how closures work.

Let us have an array of links, and our task is to make sure that when you click on each one, its serial number is displayed as an alert.
The first solution that comes to mind looks like this:

Code: for (var i = 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 links.length. Why is this happening? Due to the closure, the declared auxiliary variable i continues to exist even 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 is the value we see when clicking.

This problem is solved as follows:

Code: for (var i = 0; i< links.length; i++) {
(function(i) (
links[i].onclick = function() (
alert(i);
}
))(i);
}

Here, with the help of another closure, we "shadow" the variable i, creating a copy of it in its local scope at each step of the loop. Thanks to this, everything now works as intended.

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

PS
To save between calls it is easier to use func_name.attr like:

Code: function countIt(reset) (
if (reset ||! countIt.cnt) countIt.cnt = 0;
return countIt.cnt++;

In programming, a closure, or "closure" in English, is a method of implementing a binding context name in a first-class function language. Operationally, it is a record that stores a function along with its environment. The 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 were developed in the 1960s for the mechanical evaluation of expressions in calculus and implemented in 1970 as a feature of the PAL programming language to support lexically scoped first-class functions. Peter Lundeen defined the term "closure" in 1964 with an environment and control applied to the SECD machine for the purpose of evaluating lambda expressions bound by a lexical environment, resulting in them being closed or closed in Javascript.

This explanation was introduced in 1975 as a lexically restricted variant of LISP and became widespread. The lexical environment is the set of real variables in a program. It consists of an internal lexical environment and references to an external environment called non-local variables.

Lexical closures in Javascript are functions with its external environment. As in JavaScript, all variables have a type reference. JS only uses binding by reference - which is consistent in C++11 - and the lifetime of non-local variables captured by a function is extended to the lifetime of the function.

Closures in Javascript typically appear in languages ​​with first-class values. Such languages ​​allow functions to be passed as arguments. And also return from function calls and bind to variable names. This is similar to simple types such as strings and integers.

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 the code for the lambda expression and a reference to the threshold variable, which is the free variable within 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 result list and which should be discarded.

Since there is a closure in the threshold value, the latter can use it every time filter calls it. The filter function itself can be defined in a completely separate file. Here is the same example, rewritten in JS. It demonstrates how closures work under the hood in Javascript.

The keyword here is used instead of the global filter function, but otherwise the structure and effect of the code is the same. A function can create a closure and return it because it then survives the execution of the function, with the variables f and dx continuing to function after the derivative, even if the execution has left their scope and they are no longer visible.

In languages ​​without closures, the lifetime of an automatic local variable is the same as the execution of the stack frame where the 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.

The advantage of a closure is that it preserves the scope, the "chain of visibility" of the outer or "parent" execution context. This behavior can be used in several ways and has become a useful tool for preventing a number of JavaScript errors. One of the most common is the "loop" problem.

The 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 is changed in the context of loops before calling the new function. Closures used in this way no longer have referential transparency and are therefore no longer pure functions, however, they are commonly used in impure functional languages ​​such as Scheme. In order to understand what closures are in Javascript, you need to look at their use cases. In fact, in practice they have many uses:

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

According to MDN (Mozilla Developer Network) "Closures are functions with independent variables that 'remember' the environment of their creation." And typically, when a function exits, its local variables no longer exist. To understand how closures work in Javascript, you can look at several mechanisms. The first is formal logic. For example, by using the logName function, which takes one name as a parameter and logs it. Then I create a for loop to iterate through the list of names, set the 1st timeout, and then call the logName function passing on 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. This mechanism alone allows many people to do incredible things, such as assigning a function to a variable to be called later, or passing it as a parameter to another function.

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

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

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

Or if you do not intend to re-process 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 through the variable. For example, take the do function from earlier:

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

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

In reality, this 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 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 visibility level, in the same class or at the global level. On the other hand, in JavaScript, a local function disappears like other local variables once the parent function ends, so it is not visible from other functions.

It's actually complicated, but JavaScript has a way to track the visibility of variables, and even in two ways. The assignment of a global variable in JavaScript has the same mechanism as in Java - complex objects, arrays, DOM elements and others are passed by reference, so in the following code:

var tab = ; var tab2 = tab.

Where, tab and tab2 are two references to the same table, technically they are pointers managed by the garbage collector. Functions are also passed by reference. The globalFn variable is no longer hidden. Order allows this to happen, as demonstrated by the Javascript closure problem.

This is how you can retrieve a function from a local context if the function satisfies other local variables. A simple example: auto-increment, a function that returns an integer that is incremented by 1 each time it is called. Specifically, we need an inc function that behaves like this:

// retourne 0 inc();

// retourne 1 inc();

// retourne 2 inc();

With a closure it looks like:

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

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

var inc1 = makeInc();

var inc2 = makeInc();

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

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

Naturally, A.x and B.x are not the same variable. However, if you just want to run a script without requiring variables to be saved for others, you can use an anonymous function like a closure. This gives a somewhat strange syntax. While the two lines of code in the middle are quite common, on the other hand, the function that is around is executed on the fly. Pay attention to the parentheses () at the end. And to be able to do 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 conflicts or clunkiness, but also against XSS attacks, user variables are protected, no one can change them to affect the behavior of the script.

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

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

Javascript programming in loops

When a user does large amounts of Javascript programming, it becomes difficult to avoid loops. This drives some people crazy, leading them to believe that every Javascript implementation is seriously flawed. If a developer already has a loop that he doesn't want to convert to use the iterator function, all he needs to do is a closure in which he defines new variables. They record the current value of variables that change at each iteration. The trick to variable capture is that the outer closure is executed immediately during the current iteration of the loop. You can use one of these two example approaches

Now there is another simplified solution to this problem as the 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 being fixed by a closure inside the loop. However, it must be taken into account that it does not continue to exist after the end of one iteration of the loop, since it is local.

Loop and function

A for loop in JavaScript is not represented in the same way as a for loop in C or Java. It's actually more like PHP. The most important thing to know about loops in JS is that they don't create scope. JS doesn't have a sphere block, only a volume function. This property can be seen in the following fragment:

function foo() (var bar = 1;

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

It is clear that bar is available throughout the function. Before the first iteration of the loop, baz will be undefined. After the loop it will have the value 41 (and i will be 42). This way, any variable declared anywhere in a function will be available everywhere in the function and will only have a value once it has been assigned to it.

Gates and aggregation

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

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

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

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

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

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

Each event handler has access to the same memory location. The only solution is to introduce another scope that "captures" the current value of data. JS only has a function scope. 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 of createEventHandler and this function is executed on every 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);

Practical example of a closure in Javascript

If the user executes a closure directly above the code in the browser, he may face a problem as he may make any syntax error. If it executes the code directly in the browser, then the chances are very high that the webpack compilation process will fail. 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 passed. Now this lexicon function also returns a function that also takes a topic argument. This function logs the output and the output has access to a variable.

The scope of the Insider functions is not limited to this function, so the concept is called Closure because it has access to the given scope of the external parameter. The returned function has access to the external lexical scope or contexts. When a developer calls a function that also returns it, the first called function variables are always available to the inner function. Below is an example with the following code.

Example of an internal function

You can learn more about closures in Javascript in the second example. Now this runtime is 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.

This way, the external environment variable still exists so that the anonymous function having 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 = ;

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

) return products;

) var soap = factory();

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

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

Creating functions on the fly

You can create a function factory - functionFactory, which performs user tasks. The resulting function from the function factory will be a closure that remembers the creation environment.

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

The above allows you to pass a single functionFactory number. functionFactory then returns a Closure that stores the value of num1. The resulting function multiplies the original num1 times the value of num2, which is passed when called.

var mult5 = functionFactory(5);

var mult10 = functionFactory(10);

The above simply creates the functions mult5 and mult10. Now you can reference any of these functions by passing a new number that needs to be multiplied by 5 or 10. Now you can see the result.

Closure is one of the most powerful features of javascript, but it cannot be used correctly without understanding the concept. They're relatively easy to create by accident, which is why Javascript closures are dangerous. Creating them has potentially harmful consequences, especially in some relatively common web browser environments. To avoid accidentally encountering disadvantages and take advantage of the advantages they offer, it is necessary to understand their mechanism.

More about closures in JavaScript

Closure is one of the powerful expressive features of JavaScript that is often neglected and even discouraged.

Indeed, short circuits are very easy to create, even inadvertently, and they can lead to problems. But in fact, they are very convenient, you just need to understand what is really happening.

Simple description

Simply put, closures are internal functions. After all, javascript allows you to create functions as the script runs. And these functions have access to the variables of the outer function.

This example creates an inner function func , from within which both local variables and the outer function variables are available:

function outer() ( var outerVar; var func = function () ( var innerVar ... x = innerVar + outerVar ) return func )

When the outer function finishes running, the inner function func remains alive and can be run elsewhere in the code.

It turns out that when func is launched, the variable of the already executed function outer is used, i.e. by the very fact of its existence, func closes onto itself the variables of the external function (or rather, of all external functions).

The most common uses of closures are to assign event handler functions:

Here, the dynamically created event handler handler uses the targetId from the external function to access the element.

If you want to go deeper and understand longer...

In reality, what happens in the Javascript interpreter is much more complex and contains much more detail than described here...

But in order to understand and use closures, it is enough to understand the internal mechanism of how functions work, at least in this, sometimes simplified form...

[]

Each execution of a function stores all variables in a special object codenamed [], which cannot be accessed explicitly, but it exists.

Each call to var ... just creates a new property of this object, and any mention of a variable is first looked for in the properties of this object.

This is the internal structure of the "scope" - an ordinary object. All changes to local variables are changes to the properties of this implicit object.

Typically, after a function has finished executing, its scope [] , that is, the entire set of local variables, is killed.

The general execution flow looks like this:

By the way, for code outside the function (and global variables in general), the role of the container object [] is performed by the window object.

Nested function scope

When one function is created inside another, a reference to an object with local variables [] of the outer function is created for it.

It is due to this that variables of the outer function can be obtained from the inner function - through a link to its [] . First we look in ourselves, then in the external [] - and so on along the chain until the window object itself.

Closure is when the local variables[] object of the outer function is kept alive after it has completed.

The inner function can access it at any time and receive the outer function variable.

For example, let's look at the function that installs event handlers:

function addHideHandler(sourceId, targetId) ( // an object [] with properties sourceId, targetId is created // write to [] the sourceNode property var sourceNode = document.getElementById(sourceId) // write to [] the handler property var handler = function () ( var targetNode = document.getElementById(targetId) targetNode.style.display = 'none' ) sourceNode.onclick = handler // function finished execution // (***) and here is the most interesting thing! }

When the function is launched, everything happens as standard:

  1. created []
  2. local variables are written there
  3. inner function gets a reference to []

But at the very end - the inner function is assigned to sourceNode.onclick . The external function has finished its work, but the internal one can run sometime later.

The javascript interpreter does not analyze whether the internal function will need variables from the external one, and what variables may be needed.

Instead, it simply leaves the entire [] external function alive.

So that when the internal function starts, if it suddenly does not find any variable in its [] - it can turn to the [] external function and find it there.

If an external function was created inside another (even more external) function, then another canned [] is added to the chain, and so on - up to the global window area.

Example for understanding

In this example, the outer function makeShout() creates the inner shout().

function makeShout() ( var phrase = "Hey!" var shout = function () ( alert (phrase) ) phrase = "Done!" return shout ) shout = makeShout() // what will it display? shout()

The shout() function, as an internal function, has access to the phrase variable. What value will it output - the first or the second?

And here is a detailed description of what is happening in the bowels of javascript:

  1. Inside makeShout()
    1. created []
    2. In [] it is written: phrase="Preved!"
    3. In [] it is written: shout=..function..
    4. shout gets a reference to [] an external function
    5. [].phrase changes to the new value "Done!"
  2. When running shout()
    1. Creates its own object []
    2. Looking for phrase in [] - not found
    3. Searching for phrase in [] external function - found the value "Done!"
    4. alert("Ready!")

That is, The inner function gets the latest value of the outer variables.

Example of erroneous use

The addEvents function takes an array of divs and assigns each one to display its number on onclick .

From the question "Why doesn't this work?" people usually start studying closures.

function addEvents(divs) ( for (var i=0 ; i

For the test example, let's make 10 multi-colored numbered divs with different colors:

function makeDivs(parentId) ( for (var i=0 ;i<10 ;i++) { var j = 9 -i var div = document.createElement ("div" ) div.style .backgroundColor = "#" +i+i+j+j+j+i div.className ="closure-div" div.style .color = "#" +j+j+i+i+i+j document.getElementById (parentId) .appendChild (div) } }

The button below will create 10 divs and call addEvents on them

If you click on divs, they all display the same alert.

This glitch arose due to the fact that all div[i].onclick functions receive the value i from one on all [] external function. And this value ([].i ) at the time the onclick handler is activated is 10 (the loop ended as soon as i==10 ).

To keep everything in order, in such cases a special technique is used - highlighting [] . The following function works correctly. Everything is the same except for div.onclick .

function addEvents2(divs) ( for (var i=0 ; i

Now everything should be fine - each div gives an alert to its number.

To assign div.onclick, a temporary function function(x) (..) is run, taking an argument x and returning a handler that takes x from the [] of that temporary function.

Function(x) (..) is used to create a function, and then (i) is used to run it with argument i .

In general, javascript is a very convenient language in this sense. Allows any construction, for example:

alert ( function a() ( return [ 5 ] ) () [ 0 ] ) // => will print 5

The temporary function function(x) (..) stops running immediately, leaving in its [] the correct value of x , equal to the current loop variable i.

When the handler is activated, alert will take the correct x value from [] the nearest external function.

In theory, these examples should be enough to understand and practically use closures.

In JavaScript, functions can be described not only one after another, but also one inside the other. When you have one function inside another, the inner function has access to the variables of the outer function.

Function external(x) ( var tmp = 3; function internal(y) ( alert(x + y + (++tmp)); // will display 16 ) internal(10); ) external(2);

This code always produces 16 because the inner function sees x, which is a variable in the outer function. In this case, the function argument. Also, internal() can see tmp from external().

This is called a closure. More precisely, the external function is called a closure, and everything inside it is called the closure environment.

Sometimes they say that a closure is a function that returns a function, this is incorrect; in order to call a function a closure, it is enough that the inner function accesses a variable from outside its scope.

Function foo(x) ( var tmp = 3; return function (y) ( alert(x + y + (++tmp)); // will also alert 16 ) ) var bar = foo(2); // bar is now a closure. bar(10);

The above function will also return 16, since bar, even after foo has completed, continues to have access to x and tmp , even though bar itself is not within the scope in which they were declared.

However, since the tmp variable is still inside the bar closure, it continues to be incremented every time bar is called.

Here is a simple example of a closure:

Var a = 10; function test() ( console.log(a); // output 10 console.log(b); // output 6 ) var b = 6; test();

When you run a function in JavaScript, an environment is created for it, that is, a list of all the variables visible to it, not only the arguments and variables declared inside it, but also outside it, in this example these are “a” and “b”.

You can create more than one closure in the same environment, returning them as an array, an object, or binding them to global variables. In this case, they will all work with the same thing the value of x or tmp without creating separate copies.

Since in our example x is a number, its value is copied to foo as its argument x .

On the other hand, JavaScript always uses references when passing objects. If you were to call foo with an object as an argument, the returned closure would return a reference to the original object!

Function foo(x) ( var tmp = 3; return function (y) ( alert(x + y + tmp); x.memb = x.memb ? x.memb + 1: 1; alert(x.memb); ) ) var age = new Number(2); var bar = foo(age); // bar is now a closure referencing age. bar(10);

As you'd expect, each call to bar(10) increments x.memb . What you might not expect is that x continues to refer to the same object as age ! After two calls to bar , age.memb will be 2! By the way, this is how memory leaks occur in HTML objects.

Last update: 03/30/2018

Closures

A closure is a construct where a function created in one scope remembers its lexical environment even when it executes outside its scope.

Closure technically has three components:

    an external function that defines some scope and in which some variables are defined - the lexical environment

    variables (lexical environment) that are defined in the outer function

    nested function that uses these variables

function outer())( // external function var n; // some variable return inner())( // nested function // actions with variable n ) )

Let's look at closures using a simple example:

Function outer())( let x = 5; function inner())( x++; console.log(x); ); return inner; ) let fn = outer(); // fn = inner, since the outer function returns the inner function // call the internal function inner fn(); // 6 fn(); // 7 fn(); // 8

Here, the outer function specifies the scope in which the inner function inner and the variable x are defined. The variable x represents the lexical environment for the inner function. In the inner function itself, we increment the x variable and output its value to the console. At the end, the outer function returns the inner function.

Let fn = outer();

Since the outer function returns the inner function, the fn variable will store a reference to the inner function. At the same time, this function remembered its environment - that is, the external variable x.

Fn(); // 6 fn(); // 7 fn(); // 8

That is, despite the fact that the variable x is defined outside the inner function, this function has remembered its environment and can use it, despite the fact that it is called outside the outer function in which it was defined. This is the essence of closures.

Let's look at another example:

Function multiply(n)( var x = n; return function(m)( return x * m;); ) var fn1 = multiply(5); var result1 = fn1(6); // 30 console.log(result1); // 30 var fn2= multiply(4); var result2 = fn2(6); // 24 console.log(result2); // 24

So here, calling the multiply() function results in calling another internal function. The internal function:

Function(m)( return x * m;);

remembers the environment in which it was created, in particular, the value of the variable x.

As a result, when calling the multiply function, the variable fn1 is defined, which represents a closure, that is, it combines two things: the function and the environment in which the function was created. The environment consists of any local variable that was in the scope of the multiply function at the time the closure was created.

That is, fn1 is a closure that contains both an internal function function(m)( return x * m;) and a variable x that existed at the time the closure was created.

When you create two closures: fn1 and fn2 , each of these closures creates its own environment.

It is important not to get confused in the parameters. When defining a closure:

Var fn1 = multiply(5);

The number 5 is passed as the n parameter to the multiply function.

When calling an internal function:

Var result1 = fn1(6);

The number 6 is passed for parameter m to the internal function function(m)( return x * m;); .

We can also use another option to call the closure:

Function multiply(n)( var x = n; return function(m)( return x * m;); ) var result = multiply(5)(6); // 30 console.log(result);

Self-Calling Functions

Typically, the definition of a function is separated from its call: first we define the function, and then we call it. But this is optional. We can also create functions that will be called immediately when defined. Such functions are also called Immediately Invoked Function Expression (IIFE).

(function())( console.log("Hello world"); )()); (function (n)( var result = 1; for(var i=1; i<=n; i++) result *=i; console.log("Факториал числа " + n + " равен " + result); }(4));

Such functions are enclosed in parentheses, and after the function is defined, parameters are passed in parentheses.