Call by value - oder was???
Timothy Truckle
- javascript
Hi Folks,
soweit ich weiß erfolgt in JavaScript die Werteübergabe an eine Funktion als "Call by value" - richtig???
Wenn ich aber ein Objekt an eine Funktion übergebe (z.B. ein INPUT-Feld ) und in der Funktion dann den Wert (value) dieses Objektes ändere, dann wird direkt im INPUT-Feld der Wert geändert. Dürfte doch eigentlich nicht passieren (nur bei Call by reference).
Kann mir das bitte mal einer erklären.
Danke
Timothy
Entweder, Du kannst in der Funktion den Wert des Objekts nicht aendern, weil Du geschrieben hast
function rechne(x){
x = 2 * x;
alert ('2 * X =',x}
rechne(document.form.element.value);
dann war das call by value.
Wenn Du dann aber in der Funktion geschrieben hast
document.form.element.value = 2*x;
dann hast Du auf das global bekannte Objekt zugegriffen und die Call-by-value Semantik total unterlaufen.
korrekter waere dann, wenn das so sein soll
document.form.element.value = rechne (document.form.element.value);
dann brauchs Du natuerlich einen Rueckgabewert.
Vielleicht solltest Du das naechste Mal Deinen Quelltext mitangeben... wenn er nicht allzu geheim ist; sonst wird Dir noch was weggeguckt!
MfG, Bio
Vielleicht solltest Du das naechste Mal Deinen Quelltext mitangeben... wenn er nicht allzu geheim ist; sonst wird Dir noch was weggeguckt!
nix geheim:
<html>
<head>
<script language="JScript">
<!--
function doit(obj)
{ obj.value="ABC" }
</script>
</head>
<body>
<input type="text" name="sm" size ="60" maxlength="60">
<br>
<button name="but" onClick="doit(sm)">Doit</button>
</body>
</html>
Das ist immer noch Call by Reference, denn sm IST ein Objekt. Bei call by value muesstest du obj.value uebergeben und duerftest in der funktion nicht auf das objekt zugreifen!
Warum soll eigentlich alles bei JS Call by Value sein? Steht das irgendwo?
Bio
Warum soll eigentlich alles bei JS Call by Value sein? Steht das irgendwo?
In z.B. Turbo-Pascal wird ein call by reference folgendermaßen definiert: Doit(var obj);
Wird "var" weggelassen, dann ist es call by value. Und z.B. in "JavaScript" von Stefan Koch - dpunkt-Verlag S.49 ff steht, das Werteübergabe in JavaScript als call by value funtioniert. Und da wie bei Turbo-Pascal in JavaScript kein "var" im Funktionsaufruf existiert frage ich mich, wie Javascript unterscheiden will, ob "by value" oder "by reference" gewünscht ist. Und das übergebene Objekt (falls Javascript bei Objekten anders als bei normalen Variablen reagiert) muß ja nicht unbedingt ein WINDOW-Object sondern z.B. kann auch ein selbst Erstelltes sein. Ich denke mal, daß Javascript da etwas "unklar" definiert ist.
Bye
Timothy
Hallo Timothy,
nix ist unklar.So wie Bio es erklärt hat, ist es schon richtig. Es ist immer call by value, bloß in Deinem Beispiel hast Du ja nicht den Wert ansich übergeben, sondern ein Objekt. Oder man sollte vielleicht besser sagen, eine Objektreferenz (sozusagen ein Zeiger auf eine Datenstruktur). Übergibst Du den jetzt an eine Funktion, so wird tatsächlich neuer Speicherplatz reserviert. Aber halt bloß für den Zeiger. Den Zeiger kannst Du jetzt "umbiegen" ohne das mit dem "Orginal" was passiert. Aber call by value macht halt bloß "flaches" kopieren. Das heißt, drunterliegende Datenstrukturen werden nicht nochmal kopiert.
Ist alles etwas kompliziert, aber ich hoffe trotzdem, daß Du mir folgen konntest ;-)
Gruß
Michael
Die Pascalprogrammierer...
nun, aus irgendeinem Grund gilt Pascal als besonders klar und strukturiert.
Aber wenn doch, wie ich sage, in JS alle Objekte GLOBAL sind, dann kannst Du natuerlich in der Funktion darauf zugreifen. und obj ist halt KEIN Wert, sondern eine Referenz auf ein Objekt, also quasi auf eine Struktur, die ein Feld value hat. Wenn Du diese Referenz uebegibst, ist es natuerlich call by reference.
Deine Funktion
function doit(obj)
{ obj.value="ABC" }
waere, wenn es anders waere, auch ziemlicher Quatsch... denn dann waere obj eine lokale numerische variable, die gar kein unterobjekt haette. Oder hast Du eine Struktur oder sowas definiert? Nein! Das wuerde also auch in Pascal keinen Sinn machen, was Du da fabriziert hast.
Schreib einfach im Quellcode obj.value = doit (obj.value), und Du hast Dein Call by Value.
Und auch wenn der Mann schreibt, dass bei JS im allgemeinen oder sonstwie call by value herrschen wuerde, dann schliesst das ein anwenden von call by reference sicher nicht aus.
Im uebrigen empfehle ich ein besseres Buch ueber JS oder einen Kurs in C.
Bio
Im uebrigen empfehle ich ein besseres Buch ueber JS oder einen Kurs in C.
Ach - das Buch ist nicht so schlecht. Und ob Doit() irgendwelchen Sinn macht sei jetzt dahingestellt. Mir ging es nur um das Verständnis. Ja - und der C-Kurs beginnt morgen 8:30 Uhr (im Ernst !!! C++ und Java)
Danke und bis zum nächsten mal
Timothy
Hallo Timothy!
soweit ich weiß erfolgt in JavaScript die Werteübergabe an eine Funktion als "Call by value" - richtig???
Meines Wissens ist das so richtig, und das gilt auch fuer Objekte.
Hier wird ein kleines, aber feines Detail wichtig: Ein Objekt in JavaScript ist eigentlich nicht das Objekt selbst, sondern nur eine Referenz auf ein Objekt. Wenn Du eine Variable hast, die ein Objekt beinhaltet, so ist der eigentliche Wert der Variable nur eine Referenz (Pointer) auf das wirkliche Objekt, dass irgendwo in den unendlichen Speicherweiten das JS-Interpreters rumhaengt.
Aeh ja - geht das auch auf Deutsch? Naja, Deutsch war das schon, aber sprechen wir doch einfach auf Code, die Sprache ist viel leichter! ;-)
Definieren wir uns also ein Objekttyp:
function Akte() {
this.X = 3;
}
und legen eine Instanz dieses Dings an:
x0 = new Akte();
x0 enthaelt jetzt die Referenz auf ein eben erzeugtes Objekt vom Typ Akte. Wir koennen jederzeit mit
alert(x0.X); // ergibt 3
auf die einzige Membervariable des Objekts zugreifen. Legen wir noch so ein Ding an und aendern den Wert in .X:
x1 = new Akte();
x1.X = 5;
alert(x1.X); // ergibt 5
alert(x0.X); // ergibt immer noch 3
Soweit, so gut. Weisen wir jetzt an x1 den Wert von x0 zu:
x1 = x0;
Es wurde jetzt die Referenz auf das erste Akte-Objekt kopiert, jetzt zeigen beide Variablen auf dasselbe Objekt. Es wurde NICHT das Objekt selbst kopiert, es gibt immernoch nur eines, das den Wert 3 in .X enthaelt. (Das andere Objekt, dessen .X == 5 war, ist bei diesem Vorgang uebrigens verlorengegangen, da die einzige Referenz auf dieses Objekt (in x1) ueberschrieben wurde.) Jetzt zeigen beide Variablen auf dasselbe Objekt:
alert(x0.X); // ergibt 3
alert(x1.X); // ergibt 3
Wenn ich jetzt ueber eine der Referenzen den Wert von .X in dem Objekt aendere, sehe ich das auch ueber die andere Referenz:
x1.X = 10;
alert(x0.X); // ergibt 10
alert(x1.X); // ergibt 10
Und jetzt wird der Effekt vielleicht klar: Du uebergibst nur eine Referenz auf das eine INPUT field (und diese Referenz wird durchaus by value uebergeben), und ueber diese Referenz-Kopie wird zugegriffen, wenn Du den Wert (.value) aenderst. Und auch die kopierte Referenz zeigt eben auf das eine INPUT.
Calocybe
Hi Calocybe,
vielen Dank für die ausführliche Erklärung. So liegt also meines Erachtens der Haken beim "Object".
»»(Das andere Objekt, dessen .X == 5 war, ist bei diesem Vorgang uebrigens verlorengegangen, da die einzige Referenz auf dieses Objekt (in x1) ueberschrieben wurde.) Jetzt zeigen beide Variablen auf dasselbe Objekt:
Dies erscheint mir aber keine optimale Lösung zu sein. Wie ist dies bei anderen Sprachen (C++ / Perl ...)?.
Auf alle Fälle weiß ich jetzt, worauf ich zu achten habe und kann mir jetzt auch einige merkwürdige Effekte bei meinen Programmierversuchen erklären.
Besten Dank also (auch an Michael für sein Posting).
Bye
Timothy
Hi nochmal!
Dies erscheint mir aber keine optimale Lösung zu sein. Wie ist dies bei anderen Sprachen (C++ / Perl ...)?.
Naja, in C++ hast Du alles selber in der Hand. Da steht ganz explixit da, ob es sich nun um einen Pointer auf irgendwas oder irgendwas an sich handelt. Das ist mir ueberhaupt das liebste, da weiss man, was man hat. Und Perl... na da kenn ich mich auch nicht so genau aus. Jedenfalls gibt es dort auch Referenzen, so wie Pointer in C/C++, aber ob man die auf so ein Objekt zeigen lassen kann, weiss ich jetzt auch nicht.
Calocybe