0

I'm working with P5.js and try to save some values in an array and than creating a copy of this array to manipulate. Unfortunately It happens that when I manipulate the second array, also the original one changes, and I can't figure out why.

var particels = []
var particelsCopy = []

function calcInitialPositions(){

  for (var i = 0; i < pixels.length; i+=4) {
    if (pixels[i] == 0){
      var x_ = i  % width
      var y_ = i / width / 2
      var coords_ = {x : x_ , y : y_}
      particels.push(coords_)
    }
  };
}

function setup() {  
  loadPixels()
  calcInitialPositions();
  particelsCopy = particels
}

function draw() {
  for (var i = 0; i < particelsCopy.length; i++) {
    particelsCopy[0].x = 99
  };
  console.log(particel[0].x)
}

Console prints 99

ruggero
  • 35
  • 3
  • Try map or filter ... Arrays love to pass by reference instead of value. Googling "how to copy an array" will give you a healthy supply of options and sample code. – Doug Jul 01 '18 at 00:45
  • https://stackoverflow.com/questions/3978492/javascript-fastest-way-to-duplicate-an-array-slice-vs-for-loop – Doug Jul 01 '18 at 00:48
  • I've tried with map and filter methods, but the 2 arrays still keep the same reference – ruggero Jul 01 '18 at 15:08
  • After several attempts I finally got it with this: `particelsCopy = JSON.parse(JSON.stringify(particels));` I Found interesting this answer: https://stackoverflow.com/a/23536726/3514331 from @tfmontague – ruggero Jul 01 '18 at 15:21

3 Answers3

1

The = operator in Javascript assigns Objects, which includes arrays, by reference not by value. So the line:

particelsCopy = particels

is redefining particelsCopy to be an alias of particels.... after that point they are the same array. You need to copy the array by value like:

particelsCopy = particels.slice();

Note this is only a shallow copy, if the array contains objects or arrays they will be copied by reference, you will have to repeat this on child items (e.g. coords_ object, though for objects the pattern is copy = Object.assign({},original);).

To deep copy everything by value, you have to do this for every child level of object/arrays. Many libraries like jQuery have ready-built functions to help this.

serakfalcon
  • 3,501
  • 1
  • 22
  • 33
0

The line:

particelsCopy = particels

makes a copy of the array reference, not the elements in the array.

You need to allocate a new array object, then copy the elements. If the elements are objects, you will have to make a shallow (or deep) copy of them as well. This solution uses Object.assign() to make a shallow copy.

particelsCopy = [] // already done previously
for (var i=0; i<particels.length; i++){
   particelsCopy[i] = Object.assign({}, particels[i]};
}
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
  • I've Tried this "for loop" solution but it doesn't work, the 2 arrays still with the same reference – ruggero Jul 01 '18 at 15:05
  • @ruggero Did you remove the particelsCopy = particels line from your code? Also, you will have to make a copy of the items in the array if they are object you will mutate. I will update the answer. – Steven Spungin Jul 01 '18 at 20:14
0

You can use destructuring to copy objects in an array

particelsCopy = particels.map(obj => ({...obj}));
Zohaib Ijaz
  • 21,926
  • 7
  • 38
  • 60