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 должны быть конкретно указаны и обработаны как таковые.