Javascript call by value und call by reference

call by value übergibt nur den Wert der Variablen, nicht aber eine Referenz

Bei der Übergabe einer Variablen an eine Funktion benutzt die Funktion den Wert der Variablen für Berechnungen. Auch wenn der Variablen innerhalb der Funktion ein neuer Wert zugewiesen wird:

Außerhalb der Funktion ändert sich der Wert der Variablen nicht.

call by value

Diese Mimic wird als call by value bezeichnet, denn der Funktion wird nur der Wert der Variablen übergeben, nicht aber die Referenz auf die Speicherstelle.

function machWas( arg ) {
   arg = 17;
}

function caller() {
   let myVar = 2000; 
   machWas(myVar);
   alert(myVar);
}

Nach dem Aufruf von machWas aus der Funktion caller ist myVar weiterhin 2000. Der Funktion machWas wurde im Grunde genommen nur eine Kopie von myVar übergeben.

call by reference

call by reference ist eine weitere Technik bei der Übernahme von Variablen in Funktionsargumenten. Bei call-by-reference kann die Funktion nicht nur die Variable für interne Berechnungen verwenden, sondern den Wert der Variablen auch verändern.

In JavaScript ist call by value bei Funktionsaufrufen mit Argumenten der Normalfall. In anderen Programmiersprachen gibt es Mechanismen, um Funktionsaufrufe als call by reference auch dann zu erzwingen, wenn das Argument kein Objekt ist. In PHP z.B. wird dem Argument ein „&“ vorangestellt, damit es beim Funktionsaufruf als Referenz auf die Speicherstelle und nicht einfach als Wert der Variablen benutzt wird (machWas(&arg)). Einen solchen Mechanismus besitzt JavaScript nicht.

Objekte als Argumente übergeben

Wenn Objekte als Argumente an eine Funktion übergeben werden, kann eine call by reference-Mimic durchgeführt werden – d.h., das Objekt wird tatsächlich innerhalb der Funktion geändert und nicht einfach nur sein Wert in Berechnungen verwendet. Ganz so einfach, wie das klingt, ist es dann aber immer noch nicht.

Call by value
let myObject = new Object();
myObject.val = 2000; 

function machWasPerValue( arg ) { 
    arg.val = 4000; 
}

machWasPerValue( myObject.val );
console.log ("myObject.val " + myObject.val);
	

Wert von myObject.val nach dem Aufruf von machWasPerValue():




	
Call by reference
let myOtherObject = new Object();
function Object2 () { this.val = 2000; }

function machWasPerReference( arg ) { 
    arg.val = 4000; 
}

machWasPerReference( myOtherObject );
console.log ("myOtherObject.val " + myOtherObject.val);
	

Wert von myOtherObject.val nach dem Aufruf von machWasPerReference():







Wie Javascript mit den übergebenen Argumenten umgeht, ist nicht immer so strikt, wie wir es von anderen Programmiersprachen her kennen.

Die primitiven Typen wie Number und String werden by value übergeben, aber ein Element vom Typ Object kann sowohl by value als auch by reference übergeben werden.

  • Wenn der pure Wert übergeben wird, wird das Argument by value übergeben,
  • wird das Objekt übergeben, wird das Argument by reference übergeben.

Funktions-Objekte

Ab Javascript 1.1 können Funktionen durch den Funktions-Konstruktor erzeugt werden.

let summe = new Funktion ( "x", "y", "return x + y" );

Ab Javascript 1.2 können Funktionen als Funktions-Literal definiert werden. Funktions-Literale werden nur einmal geparst und bleiben dann statisch.

let summe = function( x,y ) { return x + y; }

Funktions-Literale ähneln dem Funktions-Konstruktor, benutzen aber eine „normale“ Syntax, um einer Variablen eine anonyme Funktion als Wert zuzuweisen. Diese Funktionen sind anonym, da sie keinen Namen haben:

let quadrat = function( zahl ) { 
   return zahl * zahl; 
}

Das Funktions-Literal kann auch einen Namen haben, aber dieser Name gilt nur innerhalb der Funktion. Auf diese Weise können rekursive Funktionen realisiert werden:

let calc = function summe( x ) {
   if (x < 2) {
      return 1;
   } else {
      return x + summe( x - 1 );
   }
}
…

z = calc( 40 );      // Dieser Aufruf ist korrekt

z = summe( 40 );     // Dieser Aufruf funktioniert nicht

Javascript Funktions-Konstruktor

Der Funktions-Konstruktor Function in Javascript erlaubt das Erzeugen einer Variablen und Zuweisen einer Funktion als Wert. Das vordefinierte Objekt Function gibt einen String an, der als Funktion interpretiert wird. Der Funktions-Konstruktor übernimmt eine beliebige Zahl von Argumenten, die alle als String übergeben werden, wobei das letzte Argument die Anweisungen der Funktion darstellen.

// Muster
let myFunction = new Function ( [arg1, arg2, …, argN], Funktionskörper );

// Beispiel
let sum = new Function( 'x', 'y', 'return x+y;' );

myFunction ist der Name einer Variablen oder Eigenschaft eines existierenden Objekts oder ein Objekt gefolgt von einem Event Handler

body.onload = new Function();

Der Aufruf der Funktion erfolgt über den Namen der Variablen, aber die Variable enthält keinen Wert, sondern eine Referenz auf die Funktion als Wert.

summe = sum( 40, 2 );

Funktions-Objekte werden bei jedem Aufruf entwickelt und dementsprechend ist ihre Effizienz gegenüber der Deklaration einer Funktion, die einmalig zu Beginn der Ausführung geparst wird, geringer. Funktions-Objekte bei jedem Aufruf geparst, so dass der String der Argumente und der Funktionsblock aus dynamisch zugewiesenen Werten bestehen kann und die Funktion im Grunde genommen bei jedem Aufruf neu geschrieben wird.

let c;
let calc = new Function( 'x', 'y', c );

c = 'x + y';
sum = calc( 40, 2 ); // sum ist 42

c = 'x / y';
div = calc( 40, 2 ); // div ist 20

Eigenschaften von Funktionen

Da Funktion in Javascript Objekte sind, haben Funktionen auch Eigenschaften. Eine Eigenschaft length gibt die Anzahl der Argumente zurück, die von der Funktion erwartet werden.

Eine andere Eigenschaft ist die prototype-Eigenschaft. Wie bei jedem Objekt können individuelle Eigenschaften für Funktionen definiert werden. Das erlaubt das Erzeugen von Werten, die wiederholte Aufrufe der Funktion „überleben“ (man sagt auch: persistente Werte). Um eine neue Eigenschaft für eine Funktion zu erzeugen, wird ihr einfach ein Wert zugewiesen.

quad.counter = 0;     // Initialisierung; 

function quad( x ) 
{
   quad.counter++;
   Anweisungen; 
   …
}

Bei jedem Aufruf von quad wird quad.counter um 1 inkrementiert.

Javascript Call by value, Call by reference