1

I'm building a simple backup/undo functionality and failing to correctly clone an array to put into the backup. I've tried using slice() and a recursive function to "deep clone", but either the cloned array remains a copy of the latest state or it does not clone all the elements of the array.

I'm using Babel.

constructor(config) {
  this.all = [];
  this.all.colors = [5,7];
  this.all.sprites = [];
  this.all.current_sprite = 0;
  this.all.width = config.sprite_x;
  this.all.height = config.sprite_y;
  this.backup = [];
  this.backup_position = 0;     
}

Version 1 deep clone (does not work)

save_backup() {
  this.backup.push(this.deepClone(this.all));
  this.backup_position ++;
  console.log(this.backup);
}

deepClone(arr) {
  var len = arr.length;
  var newArr = new Array(len);
  for (var i=0; i<len; i++) {
    if (Array.isArray(arr[i])) {
      newArr[i] = deepClone(arr[i]);
    } else {
      newArr[i] = arr[i];
    }
  }
  return newArr;
}

Version 2 slice() (does not work).

save_backup() {
  this.backup.push(this.all.slice());
  this.backup_position ++;
  console.log(this.backup);
}

The array contains all kinds of data: integers, arrays, objects, like

colors : (2) [5, 7]
config : {setting: "c64", sprite_x: 24, sprite_y: 21, colors: Array(16), zoom: 20, …}

What am I doing wrong? Thanks a lot for your help.

Esshahn
  • 330
  • 2
  • 15
  • Couldn't you just `map` splice over the 2D array, then splice the entire array? – Carcigenicate Sep 03 '17 at 15:31
  • 1
    The array is empty. You may wanna use an object instead. – Jonas Wilms Sep 03 '17 at 15:39
  • Use `slice` to copy, not `splice` – Bergi Sep 03 '17 at 15:46
  • @Bergi: sorry, that was a typo when writing this issue down. Correcting it, thank you. – Esshahn Sep 03 '17 at 16:10
  • I got it now. First, Jonas was right, I used an array where it should have been an object. Second, I needed to clone an object, not an array. And for that I found https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript to be working. Thank you everybody for your help! – Esshahn Sep 03 '17 at 16:51

1 Answers1

0

You can use Array.map and Array spread operators to clone a 2D Array like so:

const arr1 = [
  [ 'a', 'b' ],
  [ 'r', 's' ]
];

function clone2D(a) {
  return a.map(o => [...o]);
}

const arr2 = clone2D(arr1);

arr2.push(['z']); // add el to outer
arr2[0].push('q');// add el to inner

console.log(JSON.stringify(arr1));
console.log(JSON.stringify(arr2));

Note that the string elements in the array are not cloned in this example so strings are fine but objects could still run into problems because it would keep the same reference.

styfle
  • 22,361
  • 27
  • 86
  • 128