Javascript: перегрузка оператора

Я работаю с JavaScript уже несколько дней и дошел до точки, где я хочу перегрузить операторы для моих определенных объектов.

после того, как stint на google ищет это, кажется, вы не можете официально сделать это, но есть несколько человек, утверждающих какой-то длинный способ выполнения этого действия.

в основном я сделал класс Vector2 и хочу иметь возможность делать следующее:

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.
Я делаю это:
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. 

есть ли подход, который я могу принять для перегрузки операторов в моем классе Vector2? Так как это выглядит просто уродливо.

3 ответов


как вы обнаружили, JavaScript не поддерживает перегрузку оператора. Самое близкое, что вы можете сделать, это реализовать toString (который будет вызываться, когда экземпляр должен быть принужден быть строкой) и valueOf (который будет вызван, чтобы принудить его к ряду, например, при использовании + для добавления или во многих случаях при использовании его для конкатенации, потому что + пытается сделать добавление перед конкатенацией), что довольно ограничено. Не позволяет создать Vector2 объект как результат.


для людей, приходящих к этому вопросу, которые хотят строку или число в результате (вместо Vector2), однако, вот примеры valueOf и toString. Эти примеры не продемонстрируйте перегрузку оператора, просто воспользовавшись встроенной обработкой JavaScript для преобразования в примитивы:

valueOf

этот пример удваивает значение объекта val свойство в ответ на принуждение к примитивно, например через +:

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)

или с ES2015 в 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)

или просто с объектами, не конструкторы:

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

в этом примере преобразуется значение объекта val свойство в верхнем регистре в ответ на принуждение к примитиву, например через +:

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

или с ES2015 в 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

или просто с объектами, не конструкторы:

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

как сказал Ти Джей, вы не можете перегружать операторы в JavaScript. Однако вы можете воспользоваться valueOf функция для написания Хака, который выглядит лучше, чем с помощью таких функций, как add каждый раз, но накладывает ограничения на вектор, что x и y находятся между 0 и MAX_VALUE. Вот код:

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

тогда вы можете написать такие уравнения:

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]

бумага FYI.js решает эту проблему, создавая PaperScript, автономный, ограниченный javascript с перегрузкой операторов векторов, которые затем обрабатываются обратно в javascript.

но файлы paperscript должны быть конкретно указаны и обработаны как таковые.