Attaching an exchange function event to a variable

I recently hit the closures and anonymous functions, and I wonder if my code is suitable for this (it works!):

newInput.onchange = function(x){ return function(){ PassFileName(x); } }(counter); 

therefore, it is in a loop that "stores" the current value of "counter" (1,2,3 ...). If I did not have a return function, then "counter" will always be the last value of "counter".

Am I right for this code? or is there a better way to "capture" the current counter and attach it to the onchange event?

Thank you!

+6
source share
2 answers

Yes, you are approaching it correctly, but for maximum compatibility with implementations you need to put parentheses around the function:

  newInput.onchange = (function(x){ // ^--- here return function(){ PassFileName(x); } })(counter); // ^--- and here 

Whenever you execute an expression of a function and call it immediately, you need these partners, because otherwise there is a difference in the parsing.


Update

While your approach is beautiful, it’s worth noting that it’s a little wasteful. ;-) It creates two functions at each iteration of your loop, external anonymous and internal anonymous. Both of these functions adhere (prohibition of implementation optimization, which, as you know, some engines will not have). Instead, you can only have one per loop plus one factory function:

 // In the loop newInput.onchange = makeHandler(x); // Outside the loop function makeHandler(x){ return function(){ PassFileName(x); }; } 

Some may find it easier to read (of course I do), provided that makeHandler is still close enough to a loop that you won't lose.

Using the factory function also gives you the opportunity not to close anything else in scope, although then you need to add the factory function further (for example, in a well-defined area).

You can also consider general curry , for example, one of which is represented by a prototype . A general curry that does not pass call time arguments is as follows:

 function curry(f) { var args = arguments; return function() { f.apply(undefined, args); }; } 

But it is usually more useful (but more expensive) to have one that also passes runtime arguments. Here it’s cheaply dirty (not optimized, with optimization of the call waiting time it can be noticeably reduced):

 function curry(f) { var args = Array.prototype.slice.call(arguments, 1); return function() { f.apply(undefined, args.concat(Array.prototype.slice.call(arguments))); }; } 

The advantage in both cases is that you do not close anything new, which you can avoid.


Off topic . Also, technically, you rely on horror in which a semicolon is inserted (there should be a semicolon at the end of your return ), which I always defend without relying. However, this example is pretty safe .; -)

+5
source

What you are doing is pretty standard, and there is nothing wrong with that. However, there is a similar method that I prefer:

 (function (x) { newInput.onchange = function () { PassFileName(x); }; })(counter); 

For me, this is clearer by wrapping the entire block (and indented), which I'm going to create a new area to capture the value of the variable.

+3
source

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


All Articles