JS: variable inheritance in anonymous functions - scope

Hey guys, someone from doctype sent me here. short short story:

var o="before"; x = function() //this needs to be an anonymous function { alert(o); //the variable "o" is from the parent scope }; o="after"; //this chages "o" in the anonymous function x(); //this results in in alert("after"); //which is not the way i want/need it 

actually my code is a bit more complicated.
my script iterates through many html objects and adds an event listener to each element.
I do this by declaring an anonymous function for each element and calling another function with an identifier as an argument. this identifier is represented by an "o" variable in this example.

after some thought, I understand why it is,
but is there a way to get js to evaluate o since I am declaring an anonymous function without dealing with the id attribute and getting my id from there?

my complete source code is here: http://pastebin.com/GMieerdw anonymous function is on line 303

+4
source share
3 answers

You can try using the self-start function as follows:

 var o = 0; for(var i=0;i<elements.length;i++){ (function(obj,variable){ obj.onclick = function(){ alert(variable); } })(elements[i],o); o++; } 

This should mean “o” at any value that was during the cycle, instead of warning about the final value of “o”.

Hope this helps in some way.

+6
source

You need to create a closure of the variable o . You can do this by assigning a function that takes a value, returning a function that uses that value. Your example can be changed in such a way as to obtain the desired effect:

 var o="before"; x = function(inner) { return function() { alert(inner); } } (o); //here, the anonymous function is called, which will return another function which uses o o="after"; x();//prints "before" 

A more detailed description is given in the MDC article , which contains a section on the use of closures with loops.

The same method can be applied in your loop. Something like this is what you would like to do:

 var fn = function(x, y) { return function() { rr_download_start(x, y); } } (i, this); link.addEventListener('click', fn ,false); 
+8
source

One way is to create a currying function:

 function curry(fun, arg) { return function() { return fun(arg); }; }; // start loop var o="before"; x = curry(function(o) { alert(o); }, o); o="after"; x(); // "before" 

Another way is to use an external data source - since this will depend on where the function was called, you can store the value in the DOM node to which you are attaching the handler. Thus, you can use one function instead of many anonymous functions. There are a few caveats to this method (circular links can cause memory leaks in IE6), but frameworks can have a nice clean shell for this. E. g. in jQuery you can write:

 function doStuff() { alert($(this).data('o')); } // start loop var o="before"; someDomElement.data('o', 'before'); someDomElement.bind('someEvent', doStuff); o="after"; someDomElement.trigger('someEvent'); // "before" 
0
source

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


All Articles