How does this JavaScript closure work?

Here are some JavaScript:

linkElem.click(function () { var data = linkElem.data(); alert(''+data.mls + ' ' + data.id); }); 

He works.

linkElem is the local variable that I create in the loop inside the function. I assign it some data with jQuery .data() . If I had not called .click() , linkElem would be reassigned during the loop, and then returned after the function returned. However, I created an anonymous function that references linkElem . Therefore, I am no longer sure what is going on.

I assume that all anonymous functions and linkElem created during the loop are set as UIDs and go into a constant / global scope. It's right? A restless detail would be greatly appreciated.

+4
source share
3 answers

Yes, your description is pretty close. Local storage for calling the Javascript function is just a block of memory allocated for local variables. If you β€œcaptured” it by creating another function inside the called function, the storage is saved and local variables continue their life, not suspecting that the function that gave them birth can be long.

It is important to remember that only such functions create such storage; Things like closed-circuit staples are not separate storage areas. Thus, a common mistake is to declare a variable in a function and reuse it among several functions created in the loop. This is not inherently wrong, but the effect may be unexpected:

 function whatever() { for (var i = 0; i < 3; ++i) { setTimeout(function() { alert(i); }, 5000); } } 

If you run this, you will see three warnings that all say "3". What for? Because they all have the same variable "i". You can avoid this by introducing another functional level:

 function whatever() { for (var i = 0; i < 3; ++i) { setTimeout((function(private_i) { return function() { alert(private_i); }; })(i), 5000); } } 

The wrapper function is intended to provide a local variable (parameter "private_i"), where you can copy the loop variable "i".

+4
source

However, I created an anonymous function that references linkElem. Therefore, I am no longer sure what is going on.

It is still reassigned unless you terminate it with a different level of visibility (NB: another function).

Consider the following:

 for (var j = 0;j < 10;j += 1) { arrayOfLinks[j].onclick = function () { alert(j); }; } 

In this case, all of these links will warn 10 when clicked because j is out of scope and updated.

If you create linkElem in the same way, most likely you will only get the result of the last linkElem in the loop.

This is the best way:

 linkElem.click(function () { var data = $(this).data(); // no longer dependent on `linkElem` reference alert(''+data.mls + ' ' + data.id); }); 
+1
source

Please refer to How JavaScript Blocking Works? This may help you understand the closure.

Whenever you see the function keyword in another function, the inner function has access to the variables in the outer function.

 function foo(x) { var tmp = 3; function bar(y) { alert(x + y + (++tmp)); } bar(10); } foo(2) 

This will always warn 16, because bar can access x , which was defined as an argument to foo , and can also access tmp from foo .

it closing. A function must not be returned to be called a closure. Simply accessing variables outside your immediate vocabulary creates closure .

 function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar is now a closure. bar(10); 

The above function will also warn 16, because bar can still refer to x and tmp , even if it is no longer within the scope.

However, since tmp is still hanging inside the closing bar , it also increases. It will increase every time you call bar .

The simplest example of a closure is the following:

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

When you call the Javascript function, a new execution context is created. Together with the function arguments and the parent object, this execution context also accepts all variables declared outside it (in the above example, both β€œa” and β€œb”).

You can create more than one closure function, either by returning a list of them, or by setting them to global variables. All of them will refer to the same x and the same tmp that they do not create their own copies.

[you]: Exciting, tell me more!

Here, the number x is a literal number. Like other JavaScript literals, when foo is called, the number x copied to foo as its argument is x .

JavaScript, on the other hand, always uses links when working with objects. If, say, you called foo with an object, the closure returned by it will refer 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 expected, each call to bar(10) will increment x.memb . You cannot expect x just refer to the same object as the age variable! After several calls to bar , age.memb will be 2! This link is the basis for memory leaks with HTML objects.

+1
source

Source: https://habr.com/ru/post/1312456/


All Articles