Ich arbeite jetzt seit einigen Tagen mit JavaScript und habe einen Punkt erreicht, an dem ich Operatoren für meine definierten Objekte überladen möchte.
Nach einer kurzen Zeit bei Google, in der Sie danach gesucht haben, können Sie dies anscheinend nicht offiziell tun, aber es gibt einige Leute da draußen, die eine langwierige Art und Weise behaupten, diese Aktion auszuführen.
Grundsätzlich habe ich eine Vector2-Klasse erstellt und möchte Folgendes tun können:
var x = new Vector2(10,10);
var y = new Vector2(10,10);
x += y; //This does not result in x being a vector with 20,20 as its x & y values.
Stattdessen muss ich Folgendes tun:
var x = new Vector2(10,10);
var y = new Vector2(10,10);
x = x.add(y); //This results in x being a vector with 20,20 as its x & y values.
Gibt es einen Ansatz, mit dem ich Operatoren in meiner Vector2-Klasse überladen kann? Da sieht das einfach nur hässlich aus.
javascript
operators
operator-overloading
Lee Brindley
quelle
quelle
Antworten:
Wie Sie festgestellt haben, unterstützt JavaScript das Überladen von Operatoren nicht. Das nächste, was Sie erreichen können, ist die Implementierung
toString
(die aufgerufen wird, wenn die Instanz zu einer Zeichenfolge gezwungen werden muss) undvalueOf
(die aufgerufen wird, um sie zu einer Zahl zu zwingen, z. B. wenn sie+
zum Hinzufügen verwendet wird, oder in vielen Fällen, wenn Verwenden Sie es für die Verkettung, da+
versucht wird, vor der Verkettung eine Addition vorzunehmen, was ziemlich begrenzt ist. Sie können auch keinVector2
Objekt als Ergebnis erstellen .Für Leute, die zu dieser Frage kommen und als Ergebnis eine Zeichenfolge oder Zahl (anstelle von a
Vector2
) möchten , sind hier Beispiele fürvalueOf
undtoString
. Diese Beispiele zeigen keine Operatorüberladung, sondern nutzen lediglich die integrierte Verarbeitung von JavaScript zur Konvertierung in Grundelemente:valueOf
In diesem Beispiel wird der Wert der
val
Eigenschaft eines Objekts verdoppelt , wenn es zu einem Grundelement gezwungen wird, beispielsweise über+
:Code-Snippet anzeigen
Oder mit ES2015
class
:Code-Snippet anzeigen
Oder nur mit Objekten, keine Konstruktoren:
Code-Snippet anzeigen
toString
In diesem Beispiel wird der Wert der
val
Eigenschaft eines Objekts in Großbuchstaben umgewandelt, wenn er zu einem Grundelement gezwungen wird, beispielsweise über+
:Code-Snippet anzeigen
Oder mit ES2015
class
:Code-Snippet anzeigen
Oder nur mit Objekten, keine Konstruktoren:
Code-Snippet anzeigen
quelle
Date
Konvertieren die Vergleichsoperatoren der Klasse implizit Datumsangaben mit invalueOf
? Zum Beispiel können Sie tundate2 > date1
und es wird wahr sein, wenndate2
nach erstellt wurdedate1
.>
,<
,>=
, Und<=
(aber nicht==
,===
,!=
, oder!==
verwenden) , um die Zusammenfassung Relational Vergleich Operation, die AnwendungenToPrimitive
mit Hinweis „Nummer“. Bei einemDate
Objekt ergibt sich die zurückgegebene ZahlgetTime
(der Millisekunden-seit-der-Epoche-Wert).Wie TJ sagte, können Sie Operatoren in JavaScript nicht überladen. Sie können die
valueOf
Funktion jedoch nutzen, um einen Hack zu schreiben, der besser aussieht als die Verwendung von Funktionen wieadd
jedes Mal, aber dem Vektor die Einschränkungen auferlegt, dass x und y zwischen 0 und MAX_VALUE liegen. Hier ist der Code:Dann können Sie Gleichungen wie folgt schreiben:
quelle
add
Methode geschrieben ... Etwas, das sie nicht tun wollten.+
Vorzeichen dar. Dies ist eine sehr gute Antwort, die zeigt, wie Sie vermeiden können, einen unnatürlichen Funktionsnamen für quasi-numerische Objekte aufzurufen.+
Operator haben, ist die Möglichkeit, aNumber
als Ersatz für einen der Operanden zurückzugeben. Daher muss jede Addierfunktion, dieObject
Instanzen funktioniert, das Objekt immer alsNumber
und schließlich codieren .FYI paper.js löst dieses Problem, indem PaperScript erstellt wird, ein in sich geschlossenes Javascript mit Gültigkeitsbereich und Überladung von Vektoren durch den Operator, das dann wieder in Javascript verarbeitet wird.
Die Paperscript-Dateien müssen jedoch speziell spezifiziert und als solche verarbeitet werden.
quelle
Tatsächlich gibt es eine Variante von JavaScript, die das Überladen von Operatoren unterstützt. ExtendScript, die Skriptsprache, die von Adobe-Anwendungen wie Photoshop und Illustrator verwendet wird, ist vom Operator überladen. Darin können Sie schreiben:
Dies wird ausführlicher im "Adobe Extendscript JavaScript Tools Guide" (aktueller Link hier ) beschrieben. Die Syntax basierte offenbar auf einem (inzwischen längst aufgegebenen) Entwurf des ECMAScript-Standards.
quelle
Es ist möglich, Vektormathematik mit zwei Zahlen in einer zu machen. Lassen Sie mich zunächst ein Beispiel zeigen, bevor ich erkläre, wie es funktioniert:
Ich benutze die Tatsache, dass Sie das gleiche Ergebnis erhalten, wenn Sie zwei Zahlen X-mal verschieben und sie dann addieren oder subtrahieren, bevor Sie sie zurückschieben, als hätten Sie sie zunächst nicht verschoben. In ähnlicher Weise funktioniert die skalare Multiplikation und Division für verschobene Werte symmetrisch.
Eine JavaScript-Zahl hat eine Ganzzahlgenauigkeit von 52 Bit (64-Bit-Gleitkommazahlen), daher packe ich eine Zahl in die höheren verfügbaren 26 Bits und eine in die niedrigeren. Der Code ist etwas chaotischer, weil ich signierte Nummern unterstützen wollte.
Der einzige Nachteil, den ich dabei sehen kann, ist, dass x und y im Bereich von + -33 Millionen liegen müssen, da sie jeweils in 26 Bit passen müssen.
quelle
Interessant ist auch das experimentelle Überladen von js durch Bibliotheksoperatoren . Es wird nur in einem definierten Kontext (Rückruffunktion) überladen.
quelle
Wir können reaktionsähnliche Hooks verwenden, um die Pfeilfunktion bei
valueOf
jeder Iteration mit anderen Werten als die Methode zu bewerten .Code-Snippet anzeigen
Library @ js -grundlagen / vector verwendet dieselbe Idee für Vector3.
quelle
Obwohl dies keine genaue Antwort auf die Frage ist, ist es möglich, einige der Python __magic__ -Methoden mithilfe von ES6-Symbolen zu implementieren
Mit einer
[Symbol.toPrimitive]()
Methode können Sie keinen Aufruf implizierenVector.add()
, aber Sie können Syntax wie zDecimal() + int
.quelle