Titelbild des Blogbeitrags Call-By-Value /-Reference in JavaScript

Call-by-Value vs. Call-by-Reference in JavaScript

JavaScript (JS), als eine vielseitige und dynamische Sprache, stellt zwei Kernkonzepte für die Datenübergabe in Funktionen bereit: Call-by-Value und Call-by-Reference. Diese Konzepte sind entscheidend für das Verständnis, wie die Sprache mit Daten umgeht, und sind sowohl für Programmieranfänger als auch für fortgeschrittene Entwickler von großer Bedeutung. In diesem Artikel beleuchten wir diese Konzepte mit präzisen Erklärungen und Beispielen, um ein klares Verständnis ihrer Funktionsweise und Anwendung zu vermitteln.

Backen eines Marmorkuchens

Stell dir vor, du besitzt das Rezept für einen leckeren Marmorkuchen, welches du gerne mit einem Freund teilen möchtest.

Fotokopie des Rezepts

Call-by-Value entspricht dem Vorgang, eine Fotokopie Ihres Rezepts anzufertigen und diese Ihrem Freund zu geben. Ihr Freund hat jetzt eine Kopie des Rezepts. Wenn er Änderungen daran vornimmt, etwa Zutaten hinzufügt oder weglässt, hat das keinen Einfluss auf Ihr originales Rezept. Du kannst dir also sicher sein, dass du das nächste Mal, wenn du einen Kuchen backst, weiterhin das unveränderte Originalrezept verwendest und die Änderungen deines Freundes bleiben auf seine Kopie beschränkt.

Das Originalrezept verleihen

Angenommen du schickst deinem Freund nun den Link zu deiner Google Docs Rezeptesammlung – natürlich mit Bearbeitungsrechten. Dies würde dem Prinzip von Call-by-Reference entsprechen, da jede Änderung, die dein Freund am Rezept vornimmt, auch deine originale Datei verändert. Wenn du diese nun zu einem späteren Zeitpunkt öffnen und feststellen solltest, dass aus der Prise Salz ein Esslöffel wurde, dann wäre es wohl am klügsten (und amüsantesten), deinen Freund zuerst den Kuchen kosten zu lassen.

Das hört sich doch gar nicht so schwer an, oder? Sehen wir uns nun diesen Vorgang einmal genauer an.

Datenübergabe aus technischer Sicht

Pass By Reference - Java Meme

Wie funktioniert Call-by-Value?

Bei Call-by-Value wird der Wert einer Variablen als Kopie in die Funktion übertragen. Jegliche Änderungen, die innerhalb der Funktion an diesem Wert vorgenommen werden, bleiben ohne Auswirkungen auf die ursprüngliche Variable außerhalb der Funktion. Hierfür wird ein separater Speicherplatz zugewiesen, was bedeutet, dass die Funktion in einem eigenen, neuen Speicherbereich operiert. Ein ähnliches Konzept sehen wir auch im Artikel über ECMAScript 2023/24 unter dem Abschnitt „Change Array by Copy“. Dieses kurze Codebeispiel wird im Folgenden die Funktionsweise der Variablenübergabe verdeutlichen.
Codebeispiel:

function modifyValue(val) {
  val = “Neuer Wert”;
  console.log(“In der Funktion: “, val);
}
let myVal = “Alter Wert”;
modifyValue(myVal);
console.log("Außerhalb der Funktion: ", myVal);

Ergebnis:
In der Funktion: Neuer Wert
Außerhalb der Funktion: Alter Wert

Wie funktioniert Call-by-Reference?

Bei Call-by-Reference erfolgt die Übergabe einer Variablen an eine Funktion durch ihre Referenz, also ihre Speicheradresse. Änderungen, die innerhalb der Funktion an dieser Referenz vorgenommen werden, reflektieren sich unmittelbar in der Originalvariable. Anstatt eine separate Kopie des Wertes zu bearbeiten, werden hierbei alle Änderungen auch das Ursprungsobjekt betreffen.
Technisch gesehen verwendet JavaScript immer Call-by-Value, aber im Falle von Objekten (einschließlich Arrays und Funktionen) wird der Wert der Referenz übergeben. Das bedeutet, dass die Funktion mit der Adresse (Referenz) des Objekts arbeitet, aber die Referenz selbst ist eine Kopie.
Codebeispiel:

function modifyObject(obj) {
  obj.key = “Neuer Wert”;
  console.log("In der Funktion: ", obj);
}
let myObj = { key: “Alter Wert” };
modifyObject(myObj);
console.log("Außerhalb der Funktion: ", myObj);

Ergebnis:
In der Funktion: { key: „Neuer Wert“ }
Außerhalb der Funktion: { key: „Neuer Wert“ }

Das Tassenproblem

Eines der am häufigsten verwendeten Analogien ist das Füllen einer Tasse. Angenommen, du hast eine leere Tasse. Nun möchtest du diese mit der Funktion fillCup() mit einem leckeren Tee oder Kaffee befüllen. Bei Aufruf der Funktion sieht die Tasse wie folgt aus:

Beispiel-Call-By-Value /-Reference

Wenn die Referenz in der Funktion übergeben wird, verändert sich nicht nur die Variable innerhalb der Funktion, sondern die ursprüngliche Variable wird ebenfalls verändert. Bei einem Call by Value Aufruf wird hingegen nur die Variable innerhalb der Funktion verändert, die ursprüngliche behält ihren Wert.

Häufige Missverständnisse

In der JavaScript-Entwicklung existieren häufig Missverständnisse bezüglich der Handhabung von primitiven Datentypen und Objekten sowie dem Unterschied zwischen Mutation und Reassignment. Deshalb schauen wir uns dies nun ebenfalls kurz an:

Primitive Datentypen vs. Objekte

Call-by-Value vs. Call-by-Reference:

  • Primitive Datentypen: In JavaScript werden primitive Typen wie Zahlen, Strings und Booleans immer als Call-by-Value übergeben.
    ⇾ Veränderung einer Kopie der Daten
  • Objekte: Im Gegensatz dazu werden Objekte, einschließlich Arrays und Funktionen, als Call-by-Reference übergeben. Hierbei wird nicht der eigentliche Wert übergeben, sondern eine Referenz auf das Objekt.
    ⇾ Veränderung der Originalen Daten

Mutation vs. Reassignment

Mutation von Objekten:

  • Bei der Mutation wird der Zustand eines Objekts innerhalb einer Funktion verändert. Wenn beispielsweise eine Funktion ein Objekt erhält und eine seiner Eigenschaften ändert, wird diese Änderung auch außerhalb der Funktion reflektiert. Dies liegt daran, dass die Funktion mit einer Referenz auf das Objekt und nicht mit einer unabhängigen Kopie arbeitet.

Reassignment:

  • Reassignment (Neuzuweisung) bezieht sich darauf, dass innerhalb einer Funktion eine neue Zuweisung an eine Variable erfolgt, die ein Objekt referenziert. Diese Neuzuweisung hat jedoch keinen Einfluss auf die ursprüngliche Referenz außerhalb der Funktion. Das bedeutet, dass eine Funktion, die eine Objektreferenz als Parameter erhält und diese Referenz auf ein neues Objekt umleitet, nur die lokale Kopie innerhalb ihres eigenen Scopes verändert.

Vergleich mit anderen Programmiersprachen (C++)

In C++ ist Call-by-Reference expliziter und deutlicher definiert. Wenn eine Funktion einen Parameter als Referenz (&) erhält, bedeutet dies, dass sie direkt auf die übergebene Variable zugreift und sie verändern kann. Änderungen an dieser Variablen innerhalb der Funktion spiegeln sich somit direkt in der ursprünglichen Variable wider.
Hieraus entstehen folgende Unterschiede:

  • Explizit vs. Implizit: In C++ ist Call-by-Reference explizit – man sieht an der Funktionsdefinition, ob eine Referenz übergeben wird. In JavaScript ist dies implizit: Objekte werden automatisch als Referenzen ihrer Werte übergeben.
  • Direkte Manipulation vs. Referenzmanipulation: In C++ manipuliert man direkt die Variable, die übergeben wird, nicht deren Kopie. In JavaScript manipuliert man das Objekt, auf das die übergebene Referenz zeigt.
  • Effizienz: Direkte Manipulation ist vor allem bei großen Datenmengen effizienter, da bei der indirekten Manipulation diese Daten zuerst kopiert werden müssen, was zusätzlichen Speicherplatz und Verarbeitungszeit erfordert
  • Datentypen: In C++ kann jeder Datentyp (primitive und benutzerdefinierte Typen) per Referenz übergeben werden. In JavaScript betrifft dies hauptsächlich Objekte.
    Kontrolle und Sicherheit: C++ gibt dem Programmierer mehr Kontrolle und Verantwortung, was zu leistungsfähigeren, aber auch potenziell gefährlicheren Code führen kann.

 

Fazit

Nun verstehst du die Unterschiede zwischen Call-by-Value und Call-by-Reference, was eine wesentliche Grundlage für die fehlerfreie Softwareentwicklung ist und die Verständnisse über Datenflüsse vertieft. Dieses Wissen ermöglicht es dir nicht nur, potenzielle Fehler in Ihren Programmen zu vermeiden, sondern auch metaphorisch gesprochen, das „Rezept“ deiner Anwendung zu bewahren – und so sicherzustellen, dass deine Freunde, nicht unerwartet die Zutaten deines digitalen „Kuchens“ verändern.
Falls dich dieser Artikel inspiriert hat und du dich für PHP oder JavaScript Programmierung interessierst, dann nutze die Gelegenheit und bewirb dich jetzt bei clickstorm GmbH. Wir freuen uns darauf, mehr über dich und deine Programmierleidenschaft zu erfahren!

Join Clickstorm now

 

Kommentar hinzufügen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert