I have a file where I'm exporting an object like this:
export const LINECHART2_DATA = {
series: [{
data: [],
name: 'HR',
},
{
etc...
}]
}
I'm importing it like this:
import { LINECHART2_DATA } from '../chart-options/options';
I have the following method:
prepareLineChartDataContainer(bed: BedDetails) {
//Clear data to prepare for new bed
if (bed.seriesContainer == null) {
bed.seriesContainer = LINECHART2_DATA.series.slice();
} else {
bed.seriesContainer.forEach(series => {
series.data.length = 0;
});
}
//Add data to seriesContainer
this.vitalSigns.forEach(vs => {
bed.timeWindows.forEach(tw => {
bed.seriesContainer.find(series => series.name == vs).data.push(tw['avg' + vs]);
});
});
}
As you can see above, I'm slicing the series array from LINECHART2_DATA
, then pushing some data to it. When a new bed
is passed into the method with a null seriesContainer
, it will be sliced once again, but this time it will contain the data that was added by the previous bed
. Since I am using slice()
, I was expecting to just get the value of LINECHART2_DATA
, not the reference. What am I doing wrong?
I have a file where I'm exporting an object like this:
export const LINECHART2_DATA = {
series: [{
data: [],
name: 'HR',
},
{
etc...
}]
}
I'm importing it like this:
import { LINECHART2_DATA } from '../chart-options/options';
I have the following method:
prepareLineChartDataContainer(bed: BedDetails) {
//Clear data to prepare for new bed
if (bed.seriesContainer == null) {
bed.seriesContainer = LINECHART2_DATA.series.slice();
} else {
bed.seriesContainer.forEach(series => {
series.data.length = 0;
});
}
//Add data to seriesContainer
this.vitalSigns.forEach(vs => {
bed.timeWindows.forEach(tw => {
bed.seriesContainer.find(series => series.name == vs).data.push(tw['avg' + vs]);
});
});
}
As you can see above, I'm slicing the series array from LINECHART2_DATA
, then pushing some data to it. When a new bed
is passed into the method with a null seriesContainer
, it will be sliced once again, but this time it will contain the data that was added by the previous bed
. Since I am using slice()
, I was expecting to just get the value of LINECHART2_DATA
, not the reference. What am I doing wrong?
- 3 slice() always returns a new Array, rtfm – dandavis Commented Apr 6, 2018 at 20:10
- 1 @dandavis No need to be rude, why do you think I wrote that I expected to get a new array? Clearly that is not what I am getting, though, since mutating the "new array" also mutates the original one that i sliced. – Jesper Commented Apr 6, 2018 at 20:12
- 1 @Jesper Is the array mutating, or is the data in the array mutating? – Clint Commented Apr 6, 2018 at 20:13
- 1 sorry, i was going for funny... i don't see you mutating the old or new array, just the elements, which are passed "byref". think of the array as a bus and the riders as elements; they can board a new bus without being new people. – dandavis Commented Apr 6, 2018 at 20:13
-
3
The array you get back from
.slice
is a shallow copy, which means that while the array IS new, the entries in that new array are references pointing to the same objects as the original. So when you mutate them, it will change the original objects as well. – CRice Commented Apr 6, 2018 at 20:14
2 Answers
Reset to default 10From the documentation of Array.slice:
slice does not alter the original array. It returns a shallow copy of elements from the original array. Elements of the original array are copied into the returned array as follows:
For object references (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.
For strings, numbers and booleans (not String, Number and Boolean objects), slice copies the values into the new array. Changes to the string, number or boolean in one array do not affect the other array. If a new element is added to either array, the other array is not affected.
So the behaviour you're seeing is a consequence of the shallow copy behavior of slice. If you need a deep copy so that you can freely mutate the objects without affecting the originals, you'll need to do that manually. The answers to this question show a few ways of doing so.
To prevent mutating elements of copied array you should create a copy of items as well:
bed.seriesContainer = LINECHART2_DATA.series.map((item=>Object.assign({}, item, {data: item.data.slice()}))