Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: push array onto array with for loop

Please explain this to me. I'm trying to create an array of arrays with a for loop. When it didn't work, I tried simplifying the code to understand what Javascript is doing, but the simple code doesn't make sense either.

function test(){
    var sub_array = [];
    var super_array =[];
    for (var i=1;i<=3;i++){
        sub_array.push(i);
        super_array.push(sub_array);
    }
    alert(super_array);
}

I expect to see [1; 1,2; 1,2,3]. Instead I get [1,2,3; 1,2,3; 1,2,3]. I get the same phenomenon if I loop 0-2 and assign by index.

like image 757
Eric Porterfield Avatar asked Jan 25 '12 15:01

Eric Porterfield


2 Answers

well. You have to understand, that Array, Objects, Functions, etc. are references in javascript (only Numbers(Int,Floats,etc) and Strings are passed "by-value", which means, that the value is copied/duplicated)! if you have an var a=[];, und say var b=a and add b.push("bla"), then alerting a, will show you the "bla" entry, even though you added it to b. In other words; a and b is to javascript like a note on the frige from mom saying "the sandwhich on the left is for you." And then you know, that to take the left one and not just any random sandwich from the fridge. She also could have written another note (variable b) on your house' door, so that you knew where to go and look for the sandwich if you are in a hurry. If she would have stuck a sandwich to the door.. well, that would be ackward. And JS thinks the same about it :)

so the solution to your problem is as fallows;

function test(){
    var super_array =[];
    for (var i=1;i<=3;i++){
        var subarray=[];
        for (var u=1;u<=4-i;u++){
            sub_array.push(u);
            super_array.push(subarray);
        }
    }
    alert(super_array);
}

by redefining the subarray, you create a new reference. So that the variable b (the second note on the hous' door) now points in the direction of a different sandwich - maybe dad's sandwich.

I hope I could help you understand this.

like image 68
japrescott Avatar answered Nov 06 '22 05:11

japrescott


You're always pushing a reference to the same array into your super-array.

To solve that problem, you can use slice() to clone the sub-array before pushing it:

function test() {
    var sub_array = [];
    var super_array = [];
    for (var i = 1; i <= 3; i++) {
        sub_array.push(i);
        super_array.push(sub_array.slice(0));
    }
    alert(super_array);
}

EDIT: As Dan D. rightfully points out below, you can also call concat() without arguments instead of slice(0). It's faster according to this article (I did not measure it myself):

for (var i = 1; i <= 3; i++) {
    sub_array.push(i);
    super_array.push(sub_array.concat());
}
like image 37
Frédéric Hamidi Avatar answered Nov 06 '22 04:11

Frédéric Hamidi