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