Je travaille avec JavaScript depuis quelques jours maintenant et je suis arrivé à un point où je veux surcharger les opérateurs pour mes objets définis.
Après un passage sur Google à la recherche de cela, il semble que vous ne puissiez pas le faire officiellement, mais il y a quelques personnes qui revendiquent une manière de longue haleine d'effectuer cette action.
En gros, j'ai créé une classe Vector2 et je souhaite pouvoir effectuer les opérations suivantes:
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.
Au lieu de cela, je dois faire ceci:
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.
Existe-t-il une approche que je peux adopter pour surcharger les opérateurs dans ma classe Vector2? Comme cela semble tout simplement moche.
javascript
operators
operator-overloading
Lee Brindley
la source
la source
Réponses:
Comme vous l'avez constaté, JavaScript ne prend pas en charge la surcharge d'opérateurs. Le plus proche que vous pouvez venir est d'implémenter
toString
(qui sera appelé lorsque l'instance doit être forcée à être une chaîne) etvalueOf
(qui sera appelé pour la forcer à un nombre, par exemple lors de l'utilisation+
pour l'addition, ou dans de nombreux cas lorsque l'utiliser pour la concaténation car+
essaie de faire une addition avant la concaténation), ce qui est assez limité. Ni l'un ni l'autre ne vous permet de créer unVector2
objet en conséquence.Pour les personnes qui viennent à cette question et qui veulent une chaîne ou un nombre comme résultat (au lieu d'un
Vector2
), cependant, voici des exemples devalueOf
ettoString
. Ces exemples ne montrent pas la surcharge des opérateurs, profitant simplement de la gestion intégrée de JavaScript lors de la conversion en primitives:valueOf
Cet exemple double la valeur de la
val
propriété d'un objet en réponse à une contrainte sur une primitive, par exemple via+
:Afficher l'extrait de code
Ou avec ES2015
class
:Afficher l'extrait de code
Ou juste avec des objets, pas de constructeurs:
Afficher l'extrait de code
toString
Cet exemple convertit la valeur de la
val
propriété d'un objet en majuscules en réponse à une contrainte sur une primitive, par exemple via+
:Afficher l'extrait de code
Ou avec ES2015
class
:Afficher l'extrait de code
Ou juste avec des objets, pas de constructeurs:
Afficher l'extrait de code
la source
Date
classe convertissent-ils implicitement les dates en nombres en utilisantvalueOf
? Par exemple, vous pouvez le fairedate2 > date1
et ce sera vrai si adate2
été créé aprèsdate1
.>
,<
,>=
Et<=
(mais pas==
,===
,!=
ou!==
) utiliser le Résumé Relational Comparaison opération, qui utiliseToPrimitive
avec indication « nombre ». Sur unDate
objet, cela donne le nombre quigetTime
renvoie (la valeur en millisecondes depuis l'époque).Comme TJ l'a dit, vous ne pouvez pas surcharger les opérateurs en JavaScript. Cependant, vous pouvez profiter de la
valueOf
fonction pour écrire un hack qui semble mieux que d'utiliser des fonctions comme àadd
chaque fois, mais qui impose des contraintes sur le vecteur que les x et y sont compris entre 0 et MAX_VALUE. Voici le code:Ensuite, vous pouvez écrire des équations comme celle-ci:
la source
add
méthode de l'OP ... Quelque chose qu'ils ne voulaient pas faire.+
signe. C'est une très bonne réponse qui montre comment éviter d'appeler un nom de fonction non naturel pour des objets quasi-numériques.+
opérateur est la possibilité de renvoyer aNumber
en remplacement de l'un des opérandes. Par conséquent, toute fonctionnalité d'ajout qui fonctionne avec desObject
instances doit toujours encoder l'objet en tant queNumber
, et finalement le décoder.FYI paper.js résout ce problème en créant PaperScript, un javascript autonome et à portée avec une surcharge d'opérateurs de vecteurs, qu'il traite ensuite en javascript.
Mais les fichiers paperscript doivent être spécifiquement spécifiés et traités comme tels.
la source
En fait, il existe une variante de JavaScript qui prend en charge la surcharge des opérateurs. ExtendScript, le langage de script utilisé par les applications Adobe telles que Photoshop et Illustrator, a une surcharge d'opérateurs. Dans celui-ci, vous pouvez écrire:
Ceci est décrit plus en détail dans le "Guide des outils JavaScript d'Adobe Extendscript" ( lien actuel ici ). La syntaxe était apparemment basée sur un projet (maintenant abandonné depuis longtemps) de la norme ECMAScript.
la source
Il est possible de faire des mathématiques vectorielles avec deux nombres regroupés en un seul. Permettez-moi d'abord de montrer un exemple avant d'expliquer comment cela fonctionne:
J'utilise le fait que si vous décalez un peu deux nombres X fois, puis ajoutez ou soustrayez-les avant de les recaler, vous obtiendrez le même résultat que si vous ne les aviez pas décalés au départ. De même, la multiplication et la division scalaires fonctionnent symétriquement pour les valeurs décalées.
Un nombre JavaScript a 52 bits de précision entière (flottants de 64 bits), donc je vais emballer un nombre dans les 26 bits disponibles les plus élevés, et un dans le plus bas. Le code est un peu plus compliqué car je voulais prendre en charge les nombres signés.
Le seul inconvénient que je peux voir avec cela est que le x et le y doivent être compris entre + -33 millions, car ils doivent tenir dans 26 bits chacun.
la source
Bien que ce ne soit pas une réponse exacte à la question, il est possible d'implémenter certaines des méthodes python __magic__ en utilisant les symboles ES6
Une
[Symbol.toPrimitive]()
méthode ne vous permet pas d'impliquer un appelVector.add()
, mais vous permettra d'utiliser une syntaxe telle queDecimal() + int
.la source
Intéressant est également la surcharge d'opérateur de bibliothèque expérimentale js . Il ne surcharge que dans un contexte défini (fonction de rappel).
la source
Nous pouvons utiliser des Hooks de type React pour évaluer la fonction de flèche avec différentes valeurs de
valueOf
méthode à chaque itération.Afficher l'extrait de code
Library @ js-basics / vector utilise la même idée pour Vector3.
la source