Tuesday, April 6, 2010

Creating A Javascript Function Inside A Loop

I see the following question asked quite often in #javascript: "I loop over an array of elements and attach an event handler to each one. I pass along an index/variable for such & such reason. The problem is, when the event handler is executed, the index/variable is wrong!"

Example:

for (var i = 0, n = elements.length; i<n; i++) {
  var el = elements[i];
  el.addEventListener('click', function() {
    doSomethingWith(i, el); // i, el are not what you expect!
  }, false);
}

The reason that this is true is somewhat complex, but in basic terms, the function is only actually created once (instead of once each iteration of the loop) and that one function points to the last known values of the variables it uses. For more reading, start with closures and maybe move on to the ECMA Specification, in particular section 13.2, point 1.

The fix to this problem is not too difficult. There is a specific pattern that can be used to ensure that each iteration of the loop creates a brand-new function with the correct values. I call this pattern a "generator function". It probably has a proper name, but I'm not aware of it. The basic idea is to define a function (the generator) which creates and returns functions with the proper variables defined, and then call that generator function for each iteration of the loop, passing in the appropriate values. A typical generator function looks like this:

(function(variable) {
  return function() {
    // do something with variable 
  }
})(value);

There are a few things to notice in this pattern. First is that there are two function expressions: an outer one and an inner one. The outer one is the generator function, and the inner one is the function that contains your original code. Secondly, the generator function expression is wrapped in parenthesis and immediately called with an input of "value". This means that the inner function can use the identifier "variable" and it will refer to whatever value was passed in. The result of this whole shebang is a brand-new function which uses whichever values were passed in to the generator.

Applying this concept to our original problem, we come up with:

for (var i = 0, n = elements.length; i<n; i++) {
  var el = elements[i];
  el.addEventListener('click', (function(i, el) { 
    return function() {
      doSomethingWith(i, el);
    }
  })(i, el), false);
}

It's quite close to the original code, but with a little bit of wrapping. Note that this pattern can be useful for more than just attaching event handlers, although in most cases some form of loop is involved.

117 comments:

  1. hello,
    your explanation

    "but in basic terms, the function is only actually created once (instead of once each iteration of the loop) and that one function points to the last known values of the variables it uses. For more reading, start with closures and maybe move on to the ECMA Specification, in particular section 13.2, point 1."

    is incomplete, it doesn't explain the behavior for implementations that *do not* join objects.

    ReplyDelete
  2. Your "generator function" pattern saved my day. Thanks!

    ReplyDelete
  3. I just arrived to the same conclusion after an evening of thinking... but thanks for the finer solution (I just created manually 3 different functions for the 3 iterations I needed :p )

    ReplyDelete
  4. Many thanks for this trick !

    ReplyDelete
  5. Have been looking for this for years maybe! :D

    ReplyDelete
  6. thank you so much!

    ReplyDelete
  7. THANKS A LOT!!
    I can't believe it took me so long to find this - but it was worthwhile!
    I was struggling a lot, as I'm somewhat novice to javascript, and was writing in coffeescript..
    Btw, the (single-line) expression I came up with to do the same with coffeescript is:
    el.addEventListener('click', ((i,el)->->doSomethingWith(i,el))(i,el) for el,i in elements

    ReplyDelete
  8. You should avoid creating functions in loops. This is still creating a function, but it's one less per iteration.

    function something_wrapper(i, el) {
        return function() {
            doSomethingWith(i, el);
        }
    }
    var i,el; //for loops don't introduce a scope, best not to mislead people into thinking it does.
    for (i = 0, n = elements.length; i.>
        el = elements[i];
        el.addEventListener('click', something_wrapper(i, el), false);
    }

    ReplyDelete
  9. patriots jerseys, http://www.newenglandpatriotsjerseys.us/
    saints jerseys, http://www.neworleanssaintsjerseys.us/
    fitflop, http://www.fitflop.in.net/
    karen millen uk, http://www.karenmillendressesoutlets.co.uk/
    air jordan 11 free shipping, http://www.airjordan11.net/
    hollister canada, http://www.hollistercanada.com/
    hollister uk, http://www.hollistershirts.co.uk/
    tods outlet, http://www.todsoutlet.us.com/
    air jordan 4 free shipping, http://www.airjordan4.org/
    pandora jewelry, http://www.pandora.eu.com/
    coach outlet online, http://www.coachoutletstores.com.co/
    tiffany and co, http://www.tiffanyandco.in.net/
    prada outlet, http://www.pradaoutlet.us/
    ravens jerseys, http://www.baltimoreravensjerseys.us/
    supra shoes, http://www.suprashoes.us.com/
    hogan,hogan outlet,scarpe hogan,hogan sito ufficiale,hogan interactive
    michael kors outlet, http://michaelkors.outletonlinestores.us.com/
    juicy couture tracksuit, http://www.juicycoutureoutlet.net/
    chicago bulls, http://www.chicagobullsjerseys.net/
    jets jersey, http://www.newyorkjetsjersey.us/
    cai2015912

    ReplyDelete
  10. How could i get the sender and event type?

    ReplyDelete
  11. Thanks u, i have tried and i got the answer. It is awesome :)

    ReplyDelete
  12. The name is IIFE(Immediately Invoked Function Expressions)

    ReplyDelete
  13. Il Chelsea 16-17 terzo kit dispone di una combinazione di colori tradizionale in bianco e blu. Realizzato da Adidas, la nuova terza maglia del Chelsea 2016-2017 è stato rilasciato il 29 luglio ed è impostato per funzionare come Maglia nelle Coppe.maglie calcio 2017,
    maglie calcio poco prezzo, Maglia Deportivo prezzo a poco prezzo
    Maglia real madrid 2017 prezzo

    ReplyDelete
  14. This NFL Flag for Tennessee Titans is constructed of polyester, measures 3x5 feet, and has two metal grommets for attaching to our 6' aluminum flagpoles or any of our tailgate pole systems. The perimeter of our NFL Flag for Tennessee Titans is double stitched and the team logos are screen printed into the flag so they won't peel. Because of its large size, these flags are great to hang on any wall in your game room, sports room, garage.stars and stripes flags,
    football flags salebuy Cleveland Browns house divided flags
    Pittsburgh Steelers banners shop

    ReplyDelete
  15. for beginners like me need a lot of reading and searching for information on various blogs. and articles that you share a very nice and inspires me .
    obat telat datang bulan
    obat aborsi
    cara menggugurkan kandungan
    obat telat bulan
    obat penggugur kandungan

    ReplyDelete
  16. I was reading your blog, This is really informative, Please keep me more update from your blog.

    ReplyDelete
  17. This is a very good article material and it is very useful for us all. thank you . cara menggugurkan kandungan

    ReplyDelete
  18. يمكنك الان التواصل مع اكبر شركة تنظيف بالدمام والتي تتميز بانها من اكبر الشركات التي تتبع الي مؤسسة ابراج دبي الكبري لخدمات التنظيف جميعها عن طريق ارقام الخاصة لشركة التنظيف الكبري .
    http://abraj-dubai.net/%D8%B4%D8%B1%D9%83%D8%A9-%D8%AA%D9%86%D8%B8%D9%8A%D9%81-%D8%A8%D8%A7%D9%84%D8%AF%D9%85%D8%A7%D9%85/

    ReplyDelete
  19. This blog is a great source of information which is very useful for me.

    Jual Obat Aborsi Pekanbaru

    Jual Obat Aborsi Bekasi

    Jual Obat Aborsi malang

    Jual Obat Aborsi

    Obat Aborsi semarang

    Obat Aborsi yogyakarta

    Obat Aborsi solo

    Obat Aborsi

    -Can be very slow but shows all backlinks along with their PR, Anchor and if it's a Nofollow

    ReplyDelete
  20. EFFING AWESOME! This was truly great find!

    ReplyDelete
  21. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Front end developer learn from Javascript Training in Chennai . or learn thru Javascript Training in Chennai. Nowadays JavaScript has tons of job opportunities on various vertical industry. JavaScript Training in Chennai

    ReplyDelete
  22. Liquidating checks, for instance, is a considerable measure less demanding these days than it was previously. 26 hours check cashing Chicago

    ReplyDelete
  23. Thanks for the good information, Introduce me blogging indonesia want to visit on your website and read the article that is useful for me,
    if there is time to read our contents / website please via our web site :

    gastrul

    obat telat datang bulan

    obat penggugur kandungan

    aborsi

    toko bagus

    soloco

    obat penggemuk badan

    ReplyDelete

  24. Thanks for the good information, Introduce me blogging indonesia want to visit on your website and read the article that is useful for me,
    if there is time to read our contents / website please via our web site :

    1. soloco

    2. hammer of thor

    3. titan gel

    4. vimax

    5. viagra

    6. klg pills

    ReplyDelete
  25. Speaker or Volume button not working.
    our Site is very nice
    Thanks for Fantasctic blog and its to much informatic which i never think ..Keep writing and grwoing your self
    아바타카지노
    하이게이밍
    그래프사이트
    경마사이트
    슬롯게임
    슬롯게임
    https://ocn2001.com/

    ReplyDelete
  26. Bingung mencari obat penggugur kandungan paling ampuh. Disini Toko Online jual obat cytotec

    ReplyDelete
  27. Very nice blog and articles. I am realy very happy to visit your blog. Now I am found which I actually want. I check your blog everyday and try to learn something from your blog. Thank you and waiting for your new post.

    Data Science Course

    ReplyDelete
  28. I am always searching online for articles that can help me. There is obviously a lot to know about this. I think you made some good points in Features also. Keep working, great job !

    Data Science Training

    ReplyDelete
  29. pinoybay are almost located in the whole world. So they love to watch these Pariwiki Tv Shows/ Pinoy Tv Replay on a daily basis.

    ReplyDelete
  30. GMA Network operates two National Pinoy TV Channel and Couple of Pinoy Radio channels. GMA TV is famous for Pinoy Television Shows, Pinoy Tambayan Lambingan, Pinoy Tambayan at Lambingan shows, Pinoy Tambayan shows.

    ReplyDelete
  31. Hello I am so delighted I located your blog, I really located you by mistake, while I was watching on google for something else, Anyways I am here now and could just like to say thank for a tremendous post and a all round entertaining website. Please do keep up the great work. Pinoy tv

    ReplyDelete
  32. Video khatron ke khiladi 10 Colors Tv Show Full HD Episodes Online. Khatron Ke Khiladi Season 10 is An Indian Television Series.

    ReplyDelete
  33. Bigg Boss 14 is an Indian reality television game show produced by Endemol Shine India through Viacom 18 (or colloquially Colors TV Network) and Star India Network in India subsequently it was syndicated internationally and available on online as VOD through OTT platforms of Voot and Hotstar.

    ReplyDelete
  34. Pinoy Channel is Philippines Tv shows online and Full Episode For Filipino bay and pinoy flix Pinoy Tv Get latest updates on Pinoy lambingan

    ReplyDelete
  35. 토토사이트추천
    was syndicated internationally and available on online as VOD through OTT platforms of Vo

    ReplyDelete
  36. internationally and available on online as VOD through OTT platforms of Vo
    파워볼게임

    ReplyDelete
  37. 먹튀검증
    cated internationally and available on online as VOD through OTT platforms

    ReplyDelete
  38. tionally and available on online as VOD through OT
    안전놀이터

    ReplyDelete
  39. MLB중계
    ternationally and available on online as VOD through OTT

    ReplyDelete
  40. i just love it what a work you done pinoy tambayan Visit our site

    ReplyDelete