After reviewing the provided example, here are some comments for clarification:
// The function map creates a _new_ array
// with all existing elements.
// This new array is then assigned back to the original variable,
// effectively replacing the original array.
this.list = this.list.map(item => {
// When referencing "item" here, it directly corresponds to the object element within
// the current list. Any changes made to this object will affect the original item in the list.
if (item.id === target.id) {
// These lines represent your assignments.
item.dataX = parseFloat(target.getAttribute('data-x'));
item.dataY = parseFloat(target.getAttribute('data-y'));
}
// Despite returning the item which would replace the
// existing element in the new list, the returned item itself
// remains as the actual element already present in the list.
return item;
});
So, in terms of outcome, the following code provides an equivalent functionality since you are updating the initial values within the original variable:
this.list.forEach(item => {
if (item.id === target.id) {
item.dataX = parseFloat(target.getAttribute('data-x'));
item.dataY = parseFloat(target.getAttribute('data-y'));
}
});
If you wish to perform this without mutating the original objects, you can consider the following approach:
var result = this.list.map(item => {
return target.id === item.id ? {
id: item.id,
dataX: parseFloat(target.getAttribute('data-x')),
dataY: parseFloat(target.getAttribute('data-y'))
} : item;
});
In instances where 'item' carries additional data that needs to be preserved, you might need to clone the object. One methodology could be modeling the types accordingly, like shown below:
class Item {
constructor(id, x, y) {
this.id = id;
this.dataX = dataX;
this.dataY = dataY;
}
// Immutability style setter, returns the result
// as a new instance.
withData(dataX, dataY) {
return new Item(this.id, dataX, dataY);
}
}
var result = this.list.map(item => {
return item.id === target.id ? item.withData(
parseFloat(target.getAttribute('data-x')),
parseFloat(target.getAttribute('data-y'))
) : item;
});
In the above scenario, this.list
contains the untouched original array with all its elements prior to the mapping operation.
result
consists of both 'updated' elements (new instances of elements that match target.id
) and original items that do not.
Tracking Instances...
To illustrate this further, suppose we number all instances before the map operation using 'map' and assign it back to 'this.list':
this.list
Array 1
- Item 1
- Item 2
- Item 3
- Item 4
Post-map operation, while the instances have been updated but remain the same, the array itself is now a different instance:
this.list -> map -> this.list
Array 1 Array 2 (NEW)
- Item 1 -> - Item 1
- Item 2 -> - Item 2
- Item 3 -> - Item 3
- Item 4 -> - Item 4
In comparison to the forEach example, no change occurs because the instances are updated in place:
this.list (forEach) this.list (No change)
Array 1 Array 1
- Item 1 - Item 1
- Item 2 - Item 2
- Item 3 - Item 3
- Item 4 - Item 4
In each of the immutable examples, though this.list
retains its original form, 'result' becomes a distinct array instance with matched items being altered. Here, 'Item 1' was matched and updated:
this.list -> map -> result this.list (Untouched)
Array 1 Array 2 (NEW) Array 1
- Item 1 - Item 5 (NEW) - Item 1
- Item 2 -> - Item 2 - Item 2
- Item 3 -> - Item 3 - Item 3
- Item 4 -> - Item 4 - Item 4