Javascript: operator overloading

Pracuję z JavaScript od kilku dni i doszedłem do punktu, w którym chcę przeciążać operatory dla zdefiniowanych obiektów.

Po pobycie w google szukając tego, wydaje się, że oficjalnie nie można tego zrobić, ale jest kilka osób, które twierdzą, że jakiś długi sposób wykonywania tej akcji.

W zasadzie zrobiłem klasę Vector2 i chcę być w stanie wykonać:

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.

Zamiast tego muszę to zrobić:

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. 

Czy istnieje podejście mogę podjąć do przeciążenia operatorów w mojej klasie Vector2? Jak to wygląda po prostu brzydko.

Author: Dan Mandel, 2013-10-27

3 answers

Jak już zauważyłeś, JavaScript nie obsługuje przeciążania operatorów. Najbliżej jest zaimplementować toString (która zostanie wywołana, gdy instancja musi być zmuszona do bycia ciągiem znaków) i valueOf (która zostanie wywołana, aby zmusić ją do liczby, na przykład podczas używania + do dodawania, lub w wielu przypadkach, gdy używa jej do konkatenacji, ponieważ + próbuje dodać przed konkatenacją), co jest dość ograniczone. Nie pozwala na tworzenie Vector2 obiektu jako wynik.


Dla osób, które przychodzą na to pytanie, które chcą ciąg lub liczbę jako wynik (zamiast Vector2), Oto przykłady valueOf i toString. W przeciwieństwie do języka Java, JavaScript nie jest w stanie obsługiwać żadnych funkcji, które nie są w stanie obsługiwać żadnych funkcji.]}

valueOf

Ten przykład podwaja wartość właściwości val obiektu w odpowiedzi na wymuszenie na prymitywie, na przykład poprzez +:

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)

Lub z ES2015 ' s class:

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)

Lub tylko z obiektami, bez konstruktorów:

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

W tym przykładzie wartość właściwości obiektu val jest zamieniana na wielkie litery w odpowiedzi na wymuszenie na prymitywie, na przykład poprzez +:

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

Lub z ES2015 ' s class:

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

Lub tylko z obiektami, brak konstruktorów:

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
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-05 22:02:51

Jak powiedział T. J., nie można przeciążać operatorów w JavaScript. Możesz jednak skorzystać z funkcji valueOf, aby napisać hack, który wygląda lepiej niż używanie funkcji takich jak add za każdym razem, ale nakłada ograniczenia na wektor, że x i y są między 0 a MAX_VALUE. Oto kod:

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);
};

Wtedy możesz pisać równania w ten sposób:

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
Author: user2259659,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 05:04:57

Dla twojej wiadomości.js rozwiązuje ten problem, tworząc PaperScript, samodzielny, scoped javascript z operatorem przeciążania wektorów, który następnie przetwarza z powrotem do javascript.

Ale pliki paperscript muszą być dokładnie określone i przetworzone jako takie.

 6
Author: Joshua Penman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 21:34:46