0

Why is this not working as expected:

$(function(){
   var datas=[[1],[3]];
   var functions=[];
   for(var i in datas ){ 
    var data=datas[i];
    functions.push(function(){
     $("div").append($("<p/>").text("data[0]="+data[0]+", datas["+i+"][0]="+datas[i][0]));
    });
   }
   for(var i in functions )
    functions[i](); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div />

I expect:

data[0]=1, datas[0][0]=1

data[0]=3, datas[1][0]=3

Can some one help me to understand whats going on here?

Thanks a lot, greetings Patrick

---------Solution-------

var data is past in the scope of the function but it will still change after.

Therefor the best solutions is bind():

$(function(){
   var datas=[[1],[3]];
   var functions=[];
   for(var i in datas ){ 
    var data=datas[i];
    functions.push(function(data){
     $("div").append($("<p/>").text("data[0]="+data[0]+", datas["+i+"][0]="+datas[i][0]));
    }.bind(null,data));
   }
   for(var i in functions )
    functions[i](); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
pknoe3lh
  • 374
  • 3
  • 10

1 Answers1

2

This is all about scope. Try to change

var data=datas[i];
functions.push(function(){
    $("div").append($("<p/>").text("data[0]="+data[0]+", datas["+i+"][0]="+datas[i][0]));
});

to

(function (data) {
    functions.push(function(){
        $("div").append($("<p/>").text("data[0]="+data[0]+", datas["+i+"][0]="+datas[i][0]));
    });
})(datas[i]);

Within for-loop scope value of data has changed. This is why when functions are called they use last modified value of data. That's why we created a new scope where data and function live together in a friendly fashion.

stas.yaranov
  • 1,797
  • 10
  • 17
  • 1
    I'd prefere a solution with .bind() mentioned in a duplicate flag, somehow cleaner, hwoever the above should work, anyway the question is to be closed as duplicate – mikus Nov 03 '15 at 10:08