xynon
xynon

Reputation: 59

Cloned my array, and yet the original array keeps getting modified. Why?

const queenThreat = function (board) {
  let collision = false;
  let newBoard = board.slice(0);
  // Horizontal
  let horizontal = newBoard[whiteQueen[0]];
  horizontal.splice(5, 1, 0);
  collision = horizontal.includes(1)
  return board;

// Original array

[ [ 0, 0, 0, 0, 0, 1, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 1, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ] ]
// Original array after above code despite cloning the array and only accessing the cloned array

[ [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 1, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ],
  [ 0, 0, 0, 0, 0, 0, 0, 0 ] ]

I've cloned my array using slice(), accessed it instead of the original array under //Horizontal, and yet when I return the original array it's STILL modified. What am I doing wrong? I've tried every way to create a clone of the array and they all somehow modify the original despite never accessing it.

Upvotes: 0

Views: 1180

Answers (5)

Vishakha
Vishakha

Reputation: 11

In 2024, you can use structuredClone, majorly for arrays and objects. It provides a deep clone of the given value. For shallow copy you can use the above answer given by @xynon - https://stackoverflow.com/a/60460458/11410210, which I would suggest to use as per requirement.

structuredClone example usage:

const originalArray = [1, 2, 3];
const newArray = structuredClone(originalArray);
newArray.push(4);

console.log('originalArray', originalArray); // [1, 2, 3]
console.log('newArray', newArray); // [1, 2, 3, 4]

Upvotes: 0

Dhruv Polara
Dhruv Polara

Reputation: 1

If you want to clone array you can do like this

function cloneArray (array) {
  const newArray = new Array(array.length)
                      .fill()
                      .map(_=> new Array(array.length)
                   )
  for (let i = 0; i < array.length; i++) {
    for (let j = 0; j < array[0].length; j++) {
      newArray[i][j] = array[i][j];
    }
  }
  return newArray;
}

const arr1 = [[1,2,3],[4,5,6],[7,8,9]]
const arr2 = cloneArray(arr1);
arr2[0][0] = 100;

console.log("this is arr1");
arr1.forEach((val)=>console.log(val));

console.log("this is arr2");
arr2.forEach((val)=>console.log(val));
run the code snippet and test the code it is just demo you can customize function based on your requirement

Upvotes: 0

xynon
xynon

Reputation: 59

let newBoard = JSON.parse(JSON.stringify(board));

This did the trick. I figured it had something to do with being a shallow copy, but then I'm not sure what the point of creating a copy of the same array is if you can't separately modify it?

Upvotes: 2

Hemanth S A
Hemanth S A

Reputation: 91

Array.prototype.slice() does a shallow clone. Which means if the array is contains objects, the clone will be referring to the same object.

board is a 2-dimensional array. Each element in this array is an array. board.slice() provides a shallow copy of the board. If you do something like newBoard[0] = ...., original board doesn't change. But each element within newBoard, for example newBoard[0] is still referring to the same object as before board[0]. Any change in the form of newBoard[0][0] = ... will also update board[0][0].

In order to fix this, you'd need to deep clone. There are libraries performing this already. But if your use case is just 2-dimensional array, you could do something like this:

newBoard = board.map(row => row.slice());

Upvotes: 1

curiousdev
curiousdev

Reputation: 636

This is because .slice() only performs a shallow copy, therefore some of the values are still referenced from the original array. Please see more detailed explanation in the answers to this question: What is the difference between a shallow copy and a deep copy with JavaScript arrays?

Upvotes: 2

Related Questions