1

in the following code, why does postCodes[i].countryCode return the last value in the loop, and not the current value in the loop? and how can i return the current value in the loop?

for (var i = 0; i < postCodes.length; i++) {
    for (var ind = 0; ind < salesSuite.Defaults.Countries.length; ind++) {
        if (postCodes[i].countryCode == myNamespace.Countries[ind].code) {
            $('<button/>')
                .click(function () {
                    console.log(postCodes[i].countryCode);
                })
                .appendTo($modalContent);
Rafael Herscovici
  • 16,558
  • 19
  • 65
  • 93
  • see here http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – A. Wolff Dec 06 '13 at 21:05
  • seen that, i still dont get it. If i add `console.log(postCodes[i].countryCode)` just after the `if` it returns the value, can someone explain what is happening here, and why? – Rafael Herscovici Dec 06 '13 at 21:07
  • This is a classic example of closures within a loop - read up here: http://stackoverflow.com/a/750506/448865 – cpreid Dec 06 '13 at 21:13

1 Answers1

2

Try adding a function that gets a handler which creates a local variable to hold that postCode. And of course the reason for this is the usage of shared variable i inside the handler which would have run out by the time the handler is invoked So ultimately in your handler you are trying to invoke postCodes[postCodes.length].countryCode which is same as undefined.countryCode and will throw an error..

$('<button/>')
     .click(getHandler(postCodes[i]))
     .appendTo($modalContent);
.....
.....

function getHandler(postCode){ 
// This function creates a closure variable postCode which will hold that particular postCode passed in for each invocation to be used in the function reference returned by this
  return function () {
        console.log(postCode.countryCode);
   }
}

Demo

Instead of doing all this you can utilize jquery data api to hold the postCode.

  $('<button/>')
            .click(function () {
                console.log($(this).data('postCode').countryCode);
            })
            .appendTo($modalContent).data('postCode', postCodes[i]);

Demo

PSL
  • 123,204
  • 21
  • 253
  • 243
  • i am looking for an explanation also, could you explain this? Why does it happen? – Rafael Herscovici Dec 06 '13 at 21:09
  • @Dementic Yes of course (You can read the ) by the time your handler executes on click out the value of i will be incremented to the last value. so it will always be undefined.countrycode since `postCodes[postCodes.length+1]` is undefined. – PSL Dec 06 '13 at 21:10
  • 1
    nice way to create a closure – A. Wolff Dec 06 '13 at 21:12
  • @A.Wolff Infact OP can use data api itself instead of complicating this much i believe. – PSL Dec 06 '13 at 21:15
  • What if i need to process an object? my example is simplified, but the `click` event should process an object. – Rafael Herscovici Dec 06 '13 at 21:15
  • @Dementic What?? return an object from a click handler? – PSL Dec 06 '13 at 21:15
  • @Dementic What object postCode? See my second example as well. – PSL Dec 06 '13 at 21:17
  • the object contains more data then just `postCode` e.g: postCode, countryName and so on, i need that object available in the `click` event. – Rafael Herscovici Dec 06 '13 at 21:18
  • 1
    @Dementic That is what you will have. You will have a `postCode` in your handler. Did you even try to apply this? – PSL Dec 06 '13 at 21:20
  • +1 you since it does work, but why do i need to seperate it to another function, cant i somehow put it inside the click event? – Rafael Herscovici Dec 06 '13 at 21:26
  • btw, sorry for being a pain in the ass, im just trying to figure this thing out. – Rafael Herscovici Dec 06 '13 at 21:27
  • @Dementic You should read about closures, this is a very good answer with a great explanation http://stackoverflow.com/questions/111102/how-do-javascript-closures-work – PSL Dec 06 '13 at 21:36