Verschiedene Arten von Argumentausdrücken in JavaScript
Operatorausdrücke als Argumentausdrücke
Da ein Argumentausdruck ein ein im Prinzip beliebiger Ausdruck sein kann, darf auch ein Operatorausdruck (wie unten »2 + 3.5«) als Argumentausdruck verwendet werden. Der Argumentwert ist dann der Wert des verwendeten Operatorausdrucks.
- Auswertung
this.Math.floor( 2 + 3.5 )
5
Bei der Auswertung solch eines Aufrufs muß zuerst der Operatorausdruck ausgewertet werden. Dieser hat in dem obigen Beispiel den Wert »5.5«. Dann wird die Inkarnation »this.Math.floor( 5.5 )« hergestellt und als Operation ausgeführt; sie liefert schließlich das Ergebnis »5.0«.
Die Reihenfolge der Auswertung ist hier also genau anders herum als die Reihenfolge im Quelltext. Im Quelltext steht (beim Lesen von links nach rechts) zuerst »floor« und dann »+«. Ausgewertet wird zuerst »+« und dann »floor«.
Operatorausdrücke als Argumentausdrücke veranschaulichen noch einmal den Unterschied zwischen Argumentausdrücken und Argumentwerten.
In den beiden folgenden Auswertungen ist der Argumentausdruck einmal »5.5« und einmal »2 + 3.5«, der Argumtwert ist aber in beiden Fällen derselben.
- Auswertung
this.Math.floor( 5.5 )
5
- Auswertung
this.Math.floor( 2 + 3.5 )
5
Für das Ergebnis einer Auswertung eines Funktionsaufrufs kommt es nur auf den Argumentwert an, nicht auf den Argumentausdruck.
Das folgende Diagramm zeigt noch einmal die einzelnen Schritte der Auswertung von »this.Math.floor( 2 + 3.5 )«.
- Schritte bei der Auswertung von »this.Math.floor( 2 + 3.5 )«
2 + 3.5
1.) | Operationsvorgang
v5.5 Operationsprodukt
2.) | Inkarnationsvorgang
v (Einsetzen des Argumentwertes)this.Math.floor( 5.5 ) Inkarnationsprodukt
3.) | Operationsvorgang
v5 Operationsprodukt
Ein Inkarnationsvorgang ist das Einsetzen von Werten für Operanden (damit sind hier auch Argumente gemeint). Beispielsweise das Einsetzen des Wertes »5.5« für den Argumentausdruck »2 + 3.5«.
Ein Inkarnationsprodukt ist das Ergebnis eines Inkarnationsvorganges, beispielsweise »this.Math.floor( 5.5 )«. In einem Inkarnationsprodukt sind alle Operanden (einschließlich der Argumenten) Werte. Falls ein Funktionsaufruf (wie beispielsweise »this.Math.floor()«) gar keine Ausdrücke enthält, so kann dieser bereits so wie er ist als Inkarnationsprodukt angesehen werden.
Falls nur von einer „Inkarnation “ gesprochen wird, so ist damit – je nach Zusammenhang – entweder der Vorgang oder das Produkt einer Inkarnation gemeint.
Ein Operationsvorgang ist die Ausführung eines Inkarnationsproduktes, beispielsweise die Auswertung von »this.Math.floor( 5.5 )«.
Ein Operationsprodukt ist das Ergebnis eines Operationsvorgangs, beispielsweise der Wert »5« als Produkt der Auswertung von »this.Math.floor( 5.5 )«.
Falls nur von einer „Operation “ gesprochen wird, so ist damit der Vorgang einer Operation gemeint.
Namen als Argumentausdrücke
Das folgende Beispiel zeigt, daß auch ein Name (hier »this.Math.PI«) als Argumentausdruck vorkommen kann. Der Argumentwert ist dann der Wert des verwendeten Namens.
- Auswertung
this.Math.floor( this.Math.PI )
3
Das folgende Diagramm zeigt die einzelnen Schritte bei der Auswertung von »this.Math.floor( this.Math.PI )«.
- Schritte bei der Auswertung von »this.Math.floor( this.Math.PI )«
this.Math.PI
1.) | Vorgang des Auslesen
v des Wertes des Namens3.141592653589793 Ausgelesener Wert
2.) | Inkarnationsvorgang
v (Einsetzen des Argumentwertes)this.Math.floor( 3.141592653589793 ) Inkarnationsprodukt
3.) | Operationsvorgang
v3 Operationsprodukt
Aufrufausdrücke als Argumentausdrücke
Das folgende Beispiel zeigt, daß auch ein Aufrufausdruck (hier »this.Math.random()«) als Argumentausdruck vorkommen kann. Der Argumentwert ist dann der Wert einer Auswertung des als Argumentausdrucks verwendeten Aufrufausdrucks.
- Auswertung
this.Math.floor( this.Math.random() )
0
Das voranstehende Beispiel zeigt, daß ein Argumentwert auch ein Laufzeitwert (also ein vor der Auswertung noch nicht bekannter Wert) sein darf. Durch Lesen des Quelltextes kann man den Argumentwert also gar nicht erfahren, man sieht nur den Argumentausdruck! Auch dies verdeutlicht wieder den Unteschied zwischen Argumentwert und Argumentausdruck.
Das folgende Diagramm zeigt die einzelnen Schritte bei der Auswertung von »this.Math.floor( this.Math.random() )«. Da der Wert einer Auswertung von »this.Math.random()« von der Auswertung abhängt, können wir hier nur einen möglichen Wert als Beispiel herausgreifen.
- Schritte bei der Auswertung von »this.Math.floor( this.Math.random() )«
this.Math.random() Inkarnationsprodukt
1.) | Operationsvorgang zur
v angegebenen Inkarnation0.8765990144933389 Operationsergebnis (Beispiel)
2.) | Inkarnationsvorgang
v (Einsetzen des Argumentwertes)this.Math.floor( 0.8765990144933389 ) Inkarnationsprodukt
3.) | Operationsvorgang
v0 Operationsprodukt
Argumentausdrücke mit Aufrufen und Operatoren
Es ist auch möglich, daß ein Argumentausdruck Namen, Operatoren und Aufrufausdrücke gleichzeitig enthält.
Wir hatten bei dem folgenden Beispielausdruck schon gesehen, daß sein Wert immer »0.0« ist.
- Auswertung
this.Math.floor( this.Math.random() )
0
Da es langweilig ist, wenn der Wert immer gleich ist, zeigen wir den folgende Beispielausdruck, welches nun sowohl einen Funktionsnamen als auch einen Operator im Argumentausdruck enthält.
- Auswertung
this.Math.floor( 3 * this.Math.random() )
0
- Auswertung
this.Math.floor( 3 * this.Math.random() )
1
- Auswertung
this.Math.floor( 3 * this.Math.random() )
2
Jede weitere Auswertung des obenstehende Ausdrucks kann nun einen anderen Wert als die vorherige Auswertung liefern.
Auch hier hängen einige Werte nun wieder von der Auswertung ab und können deswegen im folgenden nur durch willkürlich ausgewählte Beispiele dargestellt werden.
- Mögliche Schritte bei der Auswertung von »this.Math.floor( 3 * this.Math.random() ))«
this.Math.random() Inkarnationsprodukt
1.) | Vorgang der Ermittlung
v einer Zufallszahl0.5702739229044615 Zufallszahl (zwischen 0 und 1)
2.) | Inkarnationsvorgang
v (Einsetzen der Operandenwerter)3 * 0.5702739229044615 Inkarnationsprodukt
3.) | Operationsvorgang
v1.7108217687133846 Operationsprodukt (zwischen 0 und 3)
4.) | Inkarnationsvorgang
v (Einsetzen des Argumentwertes)this.Math.floor( 1.7108217687133846 ) Inkarnationsprodukt
5.) | Operationsvorgang
v1.0 Operationsprodukt (0.0, 1.0 oder 2.0)
Das folgende Diagramm zeigt den Wertebereich des Ausdrucks »this.Math.random()« mit Nummernzeichen an.
Die Werte sind darin alle gleich wahrscheinlich.
- Wertebereich des Ausdrucks »this.Math.random()«
this.Math.random()
0 0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0 2.25 2.5 2.75 3.0 3.25 3.5 3.75 4.0
| ' ' ' | ' ' ' | ' ' ' | ' ' ' |####################
Das folgende Diagramm zeigt den Wertebereich des Ausdrucks »3 * this.Math.random()« mit Nummernzeichen an.
Die Werte sind darin weiterhin gleich wahrscheinlich, da die Streckung des Bereichs an der Art der Verteilung der Werte nichts ändert.
- Wertebereich des Ausdrucks »3 * this.Math.random()«
3 * this.Math.random()
0 0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0 2.25 2.5 2.75 3.0 3.25 3.5 3.75 4.0
| ' ' ' | ' ' ' | ' ' ' | ' ' ' |############################################################
Solch eine Multiplikation eines Bereichs mit einem positiven Faktor nennt man auch Skalierung. Falls der Faktor größer als »1« ist, spricht man von einer Streckung. Falls der Faktor kleiner als »1« ist, spricht man von einer Stauchung.
Das folgende Diagramm zeigt den Wertebereich des Ausdrucks »this.Math.floor( 3 * this.Math.random() )« mit Nummernzeichen an.
Die drei Werte sind darin weiterhin gleich wahrscheinlich, weil zu jedem Wert des folgenden Diagramms ein Bereich aus dem vorigen Diagramm gehört, dessen Breite eins beträgt. Dadurch ergibt sich der Wert »1.0« gleich vielen Fällen wie der Wert »2.0« oder der Wert »3.0«.
- Wertebereich des Ausdrucks »this.Math.floor( 3 * this.Math.random() ))«
this.Math.floor( 3 * this.Math.random() ))
0 0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0 2.25 2.5 2.75 3.0 3.25 3.5 3.75 4.0
| ' ' ' | ' ' ' | ' ' ' | ' ' ' |# # #
Die Auswertung: Erster Schritt: Die Inkarnation
Wenn eine Funktion auf ein Argument angewendet wird, dann wird eine Verbindung zwischen der Funktion und dem Wert des Arguments hergestellt, die auch als Aktivierungsverbund oder als eine Inkarnation der Funktion bezeichnet wird. (Auch bei Funktionen ohne Argument gibt es eine entsprechende Vorbereitung zum Start der Funktion, die wir hier ebenfalls als „Inkarnation“ bezeichnen.)
Im Ausdruck »this.Math.abs( -3 )« ist die Verbindung zwischen dem Funktionsnamen und dem Argumentwert bereits für den Programmierer sichtbar, aber bei der Auswertung des Ausdrucks muß der Computer sie noch einmal neu anlegen. Dies ist die Inkarnation der Funktion. Das Wort „Inkarnation “ bedeutet hier den Prozeß des Zusammenfügens zweier Informationen und auch dessen Ergebnis, also die Verbindung zwischen Funktion und Argumentwert.
Die Auswertung: Zweiter Schritt: Die Ausführung
Nachdem die Inkarnation hergestellt wurde, wird sie dann als eine Operation ausgeführt. Eine Operation ist ein bestimmter Vorgang der Datenverarbeitung, der ein Ergebnis liefern kann, wie hier den Wert »-3«.
Eine Funktion alleine ist im allgemeinen noch keine bestimmte Operation, beispielsweise kann die Funktion »this.Math.abs« alleine (ohne Inkarnation) noch nicht ausgeführt werden, weil ihr ja noch ein Argumentwert fehlt. Erst mit den Werten aller Argumente zusammen wird aus einer bloßen Funktion eine bestimmte Operation.
Verwendung von »this.Math.ceil« **
Sollen ganzzahlige Zufallszahlen bei »1« beginnen, so könnte man auf die Idee kommen, dafür »this.Math.ceil« heranzuziehen. Diese Funktion rundet ihren Argumentwert auf.
Der manchmal dafür verwendete Ausdruck »this.Math.ceil( 3 * this.Math.random() ))« hat jedoch nicht die Zahlen von »1« bis »3« mit gleicher Wahrscheinlichkeit als Wert, sondern vielmehr die Zahlen von »0« bis »3«, wobei »0« aber viel unwahrscheinlicher ist, da »this.Math.random()« auch einmal den Wert »0.0« ergeben könnte. In diesem Fall wäre »this.Math.ceil( 3 * this.Math.random() ))« dann gleich »0«.
- Wertebereich des Ausdrucks »this.Math.ceil( 3 * this.Math.random() ))«
this.Math.ceil( 3 * this.Math.random() ))
0 0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0 2.25 2.5 2.75 3.0 3.25 3.5
| ' ' ' | ' ' ' | ' ' ' | ' '? # # #
Die Verwendung von »this.Math.ceil( 3 * this.Math.random() ))« ist also falsch, wenn gleich wahrscheinliche Zahlen aus dem Bereich von »1« bis »3« ausgedrückt werden sollen.