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);
}

asked Feb 19, 2020 at 9:15

3 Answers 3

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))}
]
answered Feb 19, 2020 at 9:21
Sign up to request clarification or add additional context in comments.

1 Comment

As materialStd only contains primitive types, you can use the spread operator instead of parsing, as it is slightly faster. {id:1, material: {...materialStd} },
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);
}

answered Feb 19, 2020 at 9:21

Comments

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"]

answered Feb 19, 2020 at 9:42

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.