2

I'm pretty new in JS and something weird happen to me. I try to set different value in an object and all the value of the table are changed It appears the problems come from the creation of the object via a the object call "materialStd"

Value obj.line[0].material.flow of should stay at 123 instead of 3

Is someone able to explain what is happening there Thanks

https://jsfiddle.net/vx6fno9p/5/

var materialStd = {
  flow: 123,
  name: 'Raoul'
};
var obj = {
  id: 0,
  line: [{
      id: 1,
      material: materialStd
    },
    {
      id: 2,
      material: materialStd
    },
    {
      id: 3,
      material: materialStd
    }
  ]
}

testerror();

function testerror() {
  console.info(obj);
  //On appel une fct test

  console.log('' + obj.line[0].material.flow);
  console.log('' + obj.line[1].material.flow);
  console.log('' + obj.line[2].material.flow);

  test(obj);

  console.log('' + obj.line[0].material.flow);
  console.log('' + obj.line[1].material.flow);
  console.log('' + obj.line[2].material.flow);

}

function test(objetTraiter) {
  //  objetTraiter.line[0].material.flow=1;
  // objetTraiter.line[1].material.flow=2;
  objetTraiter.line[2].material.flow = 3;
  console.log('' + objetTraiter.line[0].material.flow);
  console.log('' + objetTraiter.line[1].material.flow);
  console.log('' + objetTraiter.line[2].material.flow);

}
Akash Shrivastava
  • 1,365
  • 8
  • 16
Pierre
  • 51
  • 1

3 Answers3

1

You problem is about reference, when you write :

line: [
    {id:1, material:materialStd},
    {id:2, material:materialStd},
    {id:3, material:materialStd}
]

The same object is put at the 3 places. So when you do objetTraiter.line[2].material.flow=3, it changes the object which is present in the 3 line objects.

In Javascript, to clone data object without keeping the same reference, we can use JSON.parse(JSON.stringify(obj)). (reference)

So you could use :

line: [
    {id:1, material: JSON.parse(JSON.stringify(materialStd))},
    {id:2, material: JSON.parse(JSON.stringify(materialStd))},
    {id:3, material: JSON.parse(JSON.stringify(materialStd))}
]
robinvrd
  • 1,760
  • 12
  • 28
  • 1
    As `materialStd` only contains primitive types, you can use the spread operator instead of parsing, as it is slightly faster. `{id:1, material: {...materialStd} },` – Jacob Feb 19 '20 at 09:24
0

When you use material: materialStd, you are not getting a copy of the object materialStd, just a reference.

so when you update here objetTraiter.line[2].material.flow=3;

this actually changes the materialStd object, because objetTraiter.line[2].material has the reference to materialStd and not an independent object.

You must clone the object for you requirement. There are multiple ways to clone the object, JSON.parse(JSON.stringify(obj)) is one of it.

see How do I correctly clone a JavaScript object? for more info on object cloning.

You may find your desired results in below example

var materialStd = {
  flow: 123,
  name: 'Raoul'
};

function cloneObject(obj) {
  return JSON.parse(JSON.stringify(obj))
}

var obj = {
  id: 0,
  line: [{
      id: 1,
      material: cloneObject(materialStd)  // clones
    },
    {
      id: 2,
      material: cloneObject(materialStd)
    },
    {
      id: 3,
      material: cloneObject(materialStd)
    }
  ]
}

testerror();

function testerror() {
  console.info(obj);
  //On appel une fct test

  console.log('' + obj.line[0].material.flow);
  console.log('' + obj.line[1].material.flow);
  console.log('' + obj.line[2].material.flow);

  test(obj);

  console.log('' + obj.line[0].material.flow);
  console.log('' + obj.line[1].material.flow);
  console.log('' + obj.line[2].material.flow);

}

function test(objetTraiter) {
  //  objetTraiter.line[0].material.flow=1;
  // objetTraiter.line[1].material.flow=2;
  objetTraiter.line[2].material.flow = 3;
  console.log('' + objetTraiter.line[0].material.flow);
  console.log('' + objetTraiter.line[1].material.flow);
  console.log('' + objetTraiter.line[2].material.flow);

}
Akash Shrivastava
  • 1,365
  • 8
  • 16
0

Because pass by reference.

    var materialStd={flow:123, name:'Raoul'};
    var obj={
    id:0,
    line:[
      {id:1, material:materialStd},
      {id:2, material:materialStd},
      {id:3, material:materialStd}]
    }
    // Compare them
    console.log(
      (obj.line[0].material === obj.line[1].material)
      &&
      (obj.line[1].material === obj.line[2].material)
    ) // true

As suggested by other answers, clone a fresh reference for your intended behaviour inside obj.line[index]["material"]

Community
  • 1
  • 1
Kelsnare
  • 635
  • 5
  • 12