0

jiddle - I've got function that creates x*y array with some default value. I want this value to be some array 2-long. But it seems that by passing new Array(2) as parameter it always pass the same object, so later changing any of cell in array affects all of them. How to make this array to have every default value the same for each cell, but independent too.

On fidle I change value of some field and alert other fields that depends on first one as every cell has default value as the same object.

OPOPO
  • 473
  • 2
  • 5
  • 15
  • Make a (shallow) copy: `result[i][j] = value.slice();` – the system Mar 26 '13 at 00:25
  • Will it work with every type of value parameter? String/ multi-d array etc? – OPOPO Mar 26 '13 at 00:26
  • For that you need to create a deep copy of the array – Arun P Johny Mar 26 '13 at 00:27
  • 1
    @OPOPO: No, but the thing to understand is that while JavaScript is a pass-by-value language, you never actually have hold of an Object value... just a reference. So primitive types will automatically copy, but objects will only copy the reference. As such, Arrays need the manual copy operation. Plain Objects are a little more verbose to copy. – the system Mar 26 '13 at 00:28
  • are you using any other third party libraries like jQuery – Arun P Johny Mar 26 '13 at 00:28
  • Yes, I use jQuery. Ok, so is there any more 'nice' method to copy object for each cycle of loop inside same function? – OPOPO Mar 26 '13 at 00:29
  • @OPOPO: If `value` could be any type, then you'll need to test to see what it is, and use the appropriate technique for each case. – the system Mar 26 '13 at 00:30
  • http://stackoverflow.com/questions/728360/copying-an-object-in-javascript - what you thing about it? – OPOPO Mar 26 '13 at 00:32
  • @OPOPO: I thing that question does not talk about arrays. – Bergi Mar 26 '13 at 01:46

1 Answers1

1

I've got function that creates x*y array with some default value. I want this value to be some array 2-long

But then it's not a x*y 2-dimensional array any more, but a x*y*2 3-dimensional array! And for that, you need a different function.

it seems that by passing new Array(2) as parameter it always pass the same object, so later changing any of cell in array affects all of them.

Yes. new Array(2) creates one object, and your code constructs a 2-dimensional array with every field pointing to it.

How to make them independent?

You'll need to use a different function, like

function newB(x, y, z) {
    var result = new Array(x);
    for (var i=0; i<x; i++) {
        result[i] = new Array(y);
        for (var j=0; j<y; j++) {
            result[i][j] = new Array(z);
        }
    }
    return result;
}

var fields = newA(5, 5, 2);

Or to make it more general, you can use some factory function as a parameter, which constructs the independent values:

function newB(x, y, valuemaker) {
    if (typeof valuemaker != "function") {
        var value = valuemaker || 0;
        valuemaker = function(){ return value; };
    }
    var result = new Array(x);
    for (var i=0; i<x; i++) {
        result[i] = new Array(y);
        for (var j=0; j<y; j++) {
            result[i][j] = valuemaker();
        }
    }
    return result;
}

var fields = newA(5, 5, function() {
    return new Array(2);
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375