Javascript: surcharge de l'opérateur

je travaille avec JavaScript depuis quelques jours maintenant et j'en 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 pouvez pas officiellement le faire, mais il y a quelques personnes là-bas qui revendiquent une façon à long terme d'effectuer cette action.

en gros, j'ai fait une classe Vector2 et je veux pouvoir faire ce qui suit:

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.

à la place, 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. 

y a-t-il une approche que je peux adopter pour surcharger les opérateurs de ma classe Vector2? Comme cela semble juste laid.

59
demandé sur Dan Mandel 2013-10-27 20:51:12

3 réponses

comme vous l'avez constaté, JavaScript ne supporte pas la surcharge de l'opérateur. Le plus proche que vous pouvez venir est d'implémenter toString (qui sera appelé quand l'instance doit être forcée à être une chaîne de caractères) et valueOf (qui sera appelé pour la forcer à un nombre, par exemple en utilisant + pour addition, ou dans de nombreux cas en l'utilisant pour concaténation parce que + essaie de faire addition avant concaténation), ce qui est assez limité. Ni vous permet de créer un Vector2 objet.


pour les personnes venant à cette question qui veulent une chaîne ou un nombre comme résultat (au lieu d'un Vector2 ), cependant, voici des exemples de valueOf et toString . Ces exemples ne démontrent pas la surcharge de l'opérateur, juste en profitant de JavaScript intégré à la conversion de conversion en primitives:

valueOf

cet exemple double la valeur de la propriété val d'un objet en réponse à une contrainte exercée sur une primitive, par exemple via + :

function Thing(val) {
    this.val = val;
}
Thing.prototype.valueOf = function() {
    // Here I'm just doubling it; you'd actually do your longAdd thing
    return this.val * 2;
};

var a = new Thing(1);
var b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)

ou avec class de ES2015:

class Thing {
    constructor(val) {
      this.val = val;
    }
    valueOf() {
      return this.val * 2;
    }
}

const a = new Thing(1);
const b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)

ou juste avec des objets, aucun constructeur:

var thingPrototype = {
    valueOf: function() {
      return this.val * 2;
    }
};

var a = Object.create(thingPrototype);
a.val = 1;
var b = Object.create(thingPrototype);
b.val = 2;
console.log(a + b); // 6 (1 * 2 + 2 * 2)

toString

cet exemple convertit la valeur de la propriété val d'un objet en majuscule en réponse à une contrainte exercée sur une primitive, par exemple via + :

function Thing(val) {
    this.val = val;
}
Thing.prototype.toString = function() {
    return this.val.toUpperCase();
};

var a = new Thing("a");
var b = new Thing("b");
console.log(a + b); // AB

ou avec class de ES2015:

class Thing {
    constructor(val) {
      this.val = val;
    }
    toString() {
      return this.val.toUpperCase();
    }
}

const a = new Thing("a");
const b = new Thing("b");
console.log(a + b); // AB

ou juste avec des objets, aucun constructeur:

var thingPrototype = {
    toString: function() {
      return this.val.toUpperCase();
    }
};

var a = Object.create(thingPrototype);
a.val = "a";
var b = Object.create(thingPrototype);
b.val = "b";
console.log(a + b); // AB
73
répondu T.J. Crowder 2018-01-05 22:02:51

comme L'a dit T. J., vous ne pouvez pas surcharger les opérateurs en JavaScript. Toutefois, vous pouvez profiter de la fonction valueOf pour écrire un hack qui semble meilleur que l'utilisation de fonctions comme add à chaque fois, mais impose les contraintes sur le vecteur que les x et y sont entre 0 et MAX_VALUE. Voici le code:

var MAX_VALUE = 1000000;

var Vector = function(a, b) {
    var self = this;
    //initialize the vector based on parameters
    if (typeof(b) == "undefined") {
        //if the b value is not passed in, assume a is the hash of a vector
        self.y = a % MAX_VALUE;
        self.x = (a - self.y) / MAX_VALUE;
    } else {
        //if b value is passed in, assume the x and the y coordinates are the constructors
        self.x = a;
        self.y = b;
    }

    //return a hash of the vector
    this.valueOf = function() {
        return self.x * MAX_VALUE + self.y;
    };
};

var V = function(a, b) {
    return new Vector(a, b);
};

alors vous pouvez écrire des équations comme ceci:

var a = V(1, 2);            //a -> [1, 2]
var b = V(2, 4);            //b -> [2, 4]
var c = V((2 * a + b) / 2); //c -> [2, 4]
17
répondu user2259659 2014-10-07 05:04:57

pour information.js résout ce problème en créant PaperScript, un javascript autonome, scopé avec la surcharge par l'opérateur des vecteurs, qu'il traite ensuite de nouveau dans javascript.

mais les fichiers paperscript doivent être spécifiquement spécifiés et traités comme tels.

6
répondu Joshua Penman 2015-01-22 21:34:46