How Would You Overload the [] Operator in JavaScript

Javascript: operator overloading

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)

How would you overload the [] operator in javascript

You can't overload operators in JavaScript.

It was proposed for ECMAScript 4 but rejected.

I don't think you'll see it anytime soon.

Is there operator overloading in ES6 / TypeScript? (or how to make object invokable)

There is no formal overloading of the () operator, but the ES5 technique works fine in modern JS as well.

As far as the Typescript story on this, your code works almost as is in Typescript 3.1

function interpolator(value: number) {
return value
}
interpolator.invert = function () { }
interpolator.setDomain = function (a : number, b: number) { }
interpolator.setRange = function (a: number, b: number) { }

// and the use like so
interpolator.setDomain(0, 1)
interpolator.setRange(50, 200)
let rangeValue = interpolator(0.5) // 125);

Playgrounk link

This is due to the new feature in 3.1 called Property assignments on function declarations.

Before 3.1 you need an extra namespace to achieve a properly typed function with extra members

function interpolator(value: number) {
return value
}
namespace interpolator {
export function invert() { }
export function setDomain(a: number, b: number) { }
export function setRange (a: number, b: number) { }
}

// and the use like so
interpolator.setDomain(0, 1)
interpolator.setRange(50, 200)
let rangeValue = interpolator(0.5) // 125);

Playgrounk link

Can I overload JavaScript's indexing operator?

Operator overloading is not possible in javascript.

Check the answer given here https://stackoverflow.com/a/1711405/1903116

Overloading Arithmetic Operators in JavaScript?

As far as I'm aware, Javascript (at least as it exists now) doesn't support operator overloading.

The best I can suggest is a class method for making new quota objects from several others. Here's a quick example of what I mean:

// define an example "class"
var NumClass = function(value){
this.value = value;
}
NumClass.prototype.toInteger = function(){
return this.value;
}

// Add a static method that creates a new object from several others
NumClass.createFromObjects = function(){
var newValue = 0;
for (var i=0; i<arguments.length; i++){
newValue += arguments[i].toInteger();
}
return new this(newValue)
}

and use it like:

var n1 = new NumClass(1);
var n2 = new NumClass(2);
var n3 = new NumClass(3);

var combined = NumClass.createFromObjects(n1, n2, n3);

Can I define custom operator overloads in Javascript?

I agree that the equal function on the vector prototype is the best solution. Note that you can also build other infix-like operators via chaining.

function Vector(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}

Vector.prototype.add = function (v2) {
var v = new Vector(this.x + v2.x,
this.y + v2.y,
this.z + v2.z);
return v;
}

Vector.prototype.equal = function (v2) {
return this.x == v2.x && this.y == v2.y && this.z == v2.z;
}

You can see online sample here.

Update: Here's a more extensive sample of creating a Factory function that supports chaining.

Function overloading in Javascript - Best practices

The best way to do function overloading with parameters is not to check the argument length or the types; checking the types will just make your code slow and you have the fun of Arrays, nulls, Objects, etc.

What most developers do is tack on an object as the last argument to their methods. This object can hold anything.

function foo(a, b, opts) {
// ...
if (opts['test']) { } //if test param exists, do something..
}

foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});

Then you can handle it anyway you want in your method. [Switch, if-else, etc.]



Related Topics



Leave a reply



Submit