Javascript, Objekte, Werte und Referenzen

3. Januar 2021 · Programmierung · andreas · Kein Kommentar

Im Gegensatz zu einigen anderen Sprachen kopiert JavaScript bei einer Zuweisung lediglich bei der Verwendung primitiver Datenelemente den Wert der ursprünglichen Variablen. Bei allen anderen Datenstrukturen wird nur die Referenz kopiert, was zu unerwarteten und unerwünschten Ergebnissen führen kann.

var band = {
	name : 'Deep Purple',
	year : 1968,
	members : {
		vocals : 'Rod Evans',
		guitar : 'Ritchie Blackmore'
	}
}

Wird einer zweiten Variablen der Wert der ersten Variable zugewiesen, so wird intern keine Kopie der Werte erzeugt, sondern lediglich die Referenz auf die Werte kopiert. Dies führt dazu, daß bei einer Änderung von “band2” auch “band” geändert wird.

var band2 = band;
band2.year = 1969;

console.log(band);

{
	"name": "Deep Purple",
	"year": 1969,
	"members": {
		"vocals": "Rod Evans",
		"guitar": "Ritchie Blackmore"
	}
}

Lösungsmöglichkeit 1: Object.assign

Als erste Lösungsmöglichkeit kann “Object.assign” verwendet werden.

Hier wird eine Kopie des Objekts angelegt, die Ausgabe des Jahres ist nach der Änderung des Jahres weiterhin unverändert.

var band2 = Object.assign({}, band);
band2.year = 1969;

console.log(band);

{
	"name": "Deep Purple",
	"year": 1968,
	"members": {
		"vocals": "Rod Evans",
		"guitar": "Ritchie Blackmore"
	}
}

Allerdings ist zu beachten, daß lediglich die erste Ebene kopiert wird, da intern für “members” erneut eine Referenz verwendet wird.

band2.members.vocals = 'Ian Gillan';

console.log(band);

{
	"name": "Deep Purple",
	"year": 1968,
	"members": {
		"vocals": "Ian Gillan",
		"guitar": "Ritchie Blackmore"
	}
}

Lösungsmöglichkeit 2: spread

Die Verwendung der Spread-Syntax führt zum gleichen Ergebnis wie Object.assign.

var band2 = {...band};
band2.year = 1969;
band2.members.vocals = 'Ian Gillan';

console.log(band);

{
	"name": "Deep Purple",
	"year": 1968,
	"members": {
		"vocals": "Ian Gillan",
		"guitar": "Ritchie Blackmore"
	}
}

Lösungsmöglichkeit 3: JSON.stringify & JSON.parse

Das Erzeugen einer komplette Kopie kann erzwungen werden, wenn zum Kopieren explizit in die JavaScript Object Notation und wieder zurück gewandelt wird.

var band2 = JSON.parse(JSON.stringify(band));
band2.year = 1969;
band2.members.vocals = 'Ian Gillan';

console.log(band);

{
	"name": "Deep Purple",
	"year": 1968,
	"members": {
		"vocals": "Rod Evans",
		"guitar": "Ritchie Blackmore"
	}
}

Wer sich detaillierter mit der Thematik inklusive Lösungsansätzen für JQuery, AngularJS sowie Performance-Messungen auseinandersetzen möchte, dem sei ein Blick auf “How do I correctly clone a JavaScript object?” empfohlen.