As can be seen from the code: when an .onload occurs, it has e as input, how can i pass a value i to the callback function, so as not to replace the required e ?

for (var i in many_i) { image[i].onload = (function (e) { var important_val1 = e.target; var important_val2 = index; })(i); } 

Thank.

  • one
    So did not try? for (var i in many_i) {var index = i; image.onload = (function (e) {var important_val1 = e.target; var important_val2 = index;}); } By the way, you install onload for the same image in a loop, overwriting the previous one with each iteration - is this what you need? - VladD
  • Thank. This is how it works! In a week, for the second time, I come across a similar one and it would be useful to know whether it is possible to pass additional variables to an anonymous function without "erasing" the call function variables. * the whole code is just made up. - michael
  • one
    @michael, yes you can, just wrap with another closure that returns (return) the function that is the event handler. - zb '
  • 3
    @Vlad, it's strange that it works for you, the scope is not limited to {} but function () {} ... here is a good example, but how it should be - zb '
  • @eicto: And really, thanks for the example! In C # this would work, there the scope is limited by brackets. I am not a JS expert. - VladD

2 answers 2

Hello.

Closures are a very powerful tool, but you need to use them with some alertness =)

The point is that in your example, all created functions have access to the variable i from the scope of the parent function. To the same variable i and when accessing it, its value is obtained at the time of the call.

In order to overcome this behavior, all you need is to fix the value of i at the time of creating the callback function. This can be achieved by adding a temporary function to the code, which will save the current value i in its scope and return a handler function, which, in turn, will have access to the value i fixed in the scope of the parent temporary function

Something like this.

 var i; for(i in many_i) { image[i].onload = (function(){ var closedI = i; return function (e) { console.log(closedI, e); } })() } 

More available topic is disclosed here.

  • 3
    isn't it? for (i in many_i) {image [i] .onload = (function (i) {return function (e) {console.log (i, e);}}) (i)} well and in your console.log not closedI and i - zb ' 6:50 pm
  • Yes, your option looks cleaner. The effect is the same, just a little different approach. Thank you, fixed the error - ikoolik 6:55 pm
  • 2
    in general, there is a more different question: jslint swears at the creation of a function in a loop, but you can get around with a hack, create a function separately, like this: for (i in many_i) {image [i] .onload = sethandler (i); } function sethandler (i) {return function (e) {console.log (i, e); }; } how is supposed to do it otherwise, I do not know. in jquery, this is solved by adding .data () to the object. - zb '
  • Well, on reflection, taking the generator to a named function does not seem like such a bad maneuver. Moreover, if the handler is not limited to a couple of lines, the readability of the code in the jslint variant is even better IMO. And it is possible in more detail about a variant with .data ()? Not fully understood. - ikoolik 10:10
  • Well, taking the generator to a separate function does not resolve the issue of generating a function in a cycle (the essence of what jslint swears), about data, everything is simple, instead of generating different functions, you can write $ .data (image [i], 'index', i) and then in the handler var i = $. data (this, 'index'); and it works both for jquery objects, and for any other (excluding strings and numbers, for arrays it already works, with the exception that jQuery is added when for (var key in arr) {}) - zb '12

Any function in Javascript has links to all variables in the context where it is declared, that is, if you have a function declared inside a function, the internal function will see all the variables of the external function. To control the scope should use anonymous functions, followed by a call.

Example: Creating functions in a loop.

If we create functions that simply print the variable i they all print the value that will be after the completion of the entire cycle, in order to pass a specific value at each step of the cycle, you need to use an inline call to an anonymous function.

 !function outer() { var functions = []; for(var i = 0; i<3;i++) { //создаем и вызываем анонимную функцию, //которая будет пробрасывать нужный параметр //для создания внутренней функции !function(i) { functions.push(function() { setTimeout(function() {alert(i);}, 0); }); }(i); } for(var index in functions) { functions[index](); } }();