In diesem Kapitel lernen wir zwei verschiedene Arten kennen, Daten zu aktualisieren
Letzteres ähnelt dem erstmaligen Erstellen einer Kopie und anschließenden destruktiven Änderung, aber es geschieht beides gleichzeitig.
Der folgende Code zeigt eine Funktion, die Objekt-Eigenschaften destruktiv aktualisiert und diese auf einem Objekt anwendet.
function setPropertyDestructively(obj, key, value) {
obj[key] = value;
return obj;
}
const obj = {city: 'Berlin', country: 'Germany'};
setPropertyDestructively(obj, 'city', 'Munich');
assert.deepEqual(obj, {city: 'Munich', country: 'Germany'});Der folgende Code demonstriert die nicht-destruktive Aktualisierung eines Objekts
function setPropertyNonDestructively(obj, key, value) {
const updatedObj = {};
for (const [k, v] of Object.entries(obj)) {
updatedObj[k] = (k === key ? value : v);
}
return updatedObj;
}
const obj = {city: 'Berlin', country: 'Germany'};
const updatedObj = setPropertyNonDestructively(obj, 'city', 'Munich');
// We have created an updated object:
assert.deepEqual(updatedObj, {city: 'Munich', country: 'Germany'});
// But we didn’t change the original:
assert.deepEqual(obj, {city: 'Berlin', country: 'Germany'});Spread macht setPropertyNonDestructively() prägnanter
Beide Versionen von setPropertyNonDestructively() aktualisieren oberflächlich: Sie ändern nur die oberste Ebene eines Objekts.
Der folgende Code zeigt eine Funktion, die Array-Elemente destruktiv aktualisiert und diese auf einem Array anwendet.
function setElementDestructively(arr, index, value) {
arr[index] = value;
}
const arr = ['a', 'b', 'c', 'd', 'e'];
setElementDestructively(arr, 2, 'x');
assert.deepEqual(arr, ['a', 'b', 'x', 'd', 'e']);Der folgende Code demonstriert die nicht-destruktive Aktualisierung eines Arrays
function setElementNonDestructively(arr, index, value) {
const updatedArr = [];
for (const [i, v] of arr.entries()) {
updatedArr.push(i === index ? value : v);
}
return updatedArr;
}
const arr = ['a', 'b', 'c', 'd', 'e'];
const updatedArr = setElementNonDestructively(arr, 2, 'x');
assert.deepEqual(updatedArr, ['a', 'b', 'x', 'd', 'e']);
assert.deepEqual(arr, ['a', 'b', 'c', 'd', 'e']);.slice() und Spread machen setElementNonDestructively() prägnanter
function setElementNonDestructively(arr, index, value) {
return [
...arr.slice(0, index), value, ...arr.slice(index+1)];
}Beide Versionen von setElementNonDestructively() aktualisieren oberflächlich: Sie ändern nur die oberste Ebene eines Arrays.
Bisher haben wir Daten nur oberflächlich aktualisiert. Widmen wir uns nun dem Deep-Updating. Der folgende Code zeigt, wie man es manuell macht. Wir ändern Name und Arbeitgeber.
const original = {name: 'Jane', work: {employer: 'Acme'}};
const updatedOriginal = {
...original,
name: 'John',
work: {
...original.work,
employer: 'Spectre'
},
};
assert.deepEqual(
original, {name: 'Jane', work: {employer: 'Acme'}});
assert.deepEqual(
updatedOriginal, {name: 'John', work: {employer: 'Spectre'}});Die folgende Funktion implementiert generisches Deep-Updating.
function deepUpdate(original, keys, value) {
if (keys.length === 0) {
return value;
}
const currentKey = keys[0];
if (Array.isArray(original)) {
return original.map(
(v, index) => index === currentKey
? deepUpdate(v, keys.slice(1), value) // (A)
: v); // (B)
} else if (typeof original === 'object' && original !== null) {
return Object.fromEntries(
Object.entries(original).map(
(keyValuePair) => {
const [k,v] = keyValuePair;
if (k === currentKey) {
return [k, deepUpdate(v, keys.slice(1), value)]; // (C)
} else {
return keyValuePair; // (D)
}
}));
} else {
// Primitive value
return original;
}
}Wenn wir value als Wurzel eines Baumes betrachten, den wir aktualisieren, dann verändert deepUpdate() nur einen einzelnen Zweig tiefgreifend (Zeile A und C). Alle anderen Zweige werden oberflächlich kopiert (Zeile B und D).
So sieht die Verwendung von deepUpdate() aus