1

I'm having a trouble when I want to create a multidimensional array.

I don't know why but I get a strange behavior when I want to create a multidimensional array with an object as default value.

I have used different ways like:

The trouble appears when I want to change anyone of fields of the object.

function matrix( rows, cols, defaultValue){
  var arr = [];
  // Creates all lines:
  for(var i=0; i < rows; i++){
      // Creates an empty line
      arr.push([]);
      // Adds cols to the empty line:
      arr[i].push( new Array(cols));
      for(var j=0; j < cols; j++){
        // Initializes:
        arr[i][j] = defaultValue;
      }
  }
	return arr;
}

var myArray = matrix(5, 5, {
	status: 'OK'
});


myArray[2][1].status = 'NOT OK';

console.log('Strange behavior', myArray);

The change expands on the other positions.

Can anybody help me?

4 Answers 4

3

Because you store a reference to one and the same object over and over again, you have the behaviour as you described. To get separate objects, you could use object.assign, to make a (shallow) copy of defaultValue each time you need it:

arr[i][j] = Object.assign({}, defaultValue);

With some other ES6 features, your code could look like this:

function matrix( rows, cols, defaultValue){
  return Array.from(Array(rows), 
     row => Array.from(Array(cols), cell => Object.assign({}, defaultValue))
  );
}
var myArray = matrix(5, 5, {
	status: 'OK'
});

myArray[2][1].status = 'NOT OK';

console.log('Correct behavior', myArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

3 Comments

Great!!! cell => typeof defaultValue === 'object' ? Object.assign({}, defaultValue) : defaultValue) can be more reusable.
In that case do cell => Object(defaultValue) === defaultValue ? to make sure null is not treated as an object.
Thanks, It's very useful.
2

The problem is you're assigning the same object at each point in the matrix. So if you change the object at one point in the array, it will be changed at all other points as well. To fix, use a clone function (like underscore's or jQuery's) or instantiate a new object for each point in the matrix.

Comments

0

Instead of

arr.push([]);
// Adds cols to the empty line:
arr[i].push( new Array(cols));

try

arr.push( new Array(cols));

Comments

0

Objects are passed around by their references, so you are assigning a reference to the same object to all the cells in the matrix thus making them all the same object (changing one will cause the others to change as well). You'll have to duplicate the object. If you are using recent ECMAScripts you can use Object.assign like this:

function matrix( rows, cols, defaultValue) {
  var arr = [];
  for(var i=0; i < rows; i++) {
      var row = [];  // create a row
      arr.push(row); // push it into the matrix

      for(var j=0; j < cols; j++) {
        row[j] = Object.assign({}, defaultValue); // copy the default value and assign it to this cell
      }
  }
    return arr;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.