I've been working with JavaScript for a few days now and have got to a point where I want to overload operators for my defined objects.
After a stint on google searching for this it seems you can't officially do this, yet there are a few people out there claiming some long-winded way of performing this action.
Basically I've made a Vector2 class and want to be able to do the following:
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.
Instead I'm having to do this:
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.
Is there an approach I can take to overload operators in my Vector2 class? As this just looks plain ugly.
As you've found, JavaScript doesn't support operator overloading. The closest you can come is to implement toString
(which will get called when the instance needs to be coerced to being a string) and valueOf
(which will get called to coerce it to a number, for instance when using +
for addition, or in many cases when using it for concatenation because +
tries to do addition before concatenation), which is pretty limited. Neither lets you create a Vector2
object as a result. Similarly, Proxy
(added in ES2015) lets you intercept various object operations (including property access), but again won't let you control the result of +=
on Vector
instances.
For people coming to this question who want a string or number as a result (instead of a Vector2
), though, here are examples of valueOf
and toString
. These examples do not demonstrate operator overloading, just taking advantage of JavaScript's built-in handling converting to primitives:
valueOf
This example doubles the value of an object's val
property in response to being coerced to a primitive, for instance 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)
Or with 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)
Or just with objects, no constructors:
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
This example converts the value of an object's val
property to upper case in response to being coerced to a primitive, for instance 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
Or with 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
Or just with objects, no constructors:
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