In an effort not to pollute or extend the prototype Number object, I am attempting to create a class that extends Number. However, when I do this and then try to add anything to it or even add it to itself, it is converted back to a number.
I understand this is occurring because it is taking the numeric valueOf property value and returning that value added to another number, but I would like for the value to always retain its subclass without having to create additional methods like:
.add(x).sub(x).mul(x).div(x)
Is there a way to achieve this, similar to how both the Number and BigInt types allow for these types of computations? I could—but would prefer not to—extend the built-in Number object to support my custom methods, but anytime I try working with them now, they lose all their methods.
For example:
let num = 5;
console.log(num.constructor); // Number
num += 2;
console.log(num); // 7
console.log(num.constructor); // still Number
However, working with my extended class:
class MyNum extends Number {
constructor (num = 0) {
super(num);
}
get isEven() { return this.isInt && this % 2 === 0 }
get isOdd() { return this.isInt && this % 2 !== 0 }
}
let num = new MyNum(5);
console.log(num.constructor); // MyNum
num += 2;
console.log(num); // 7
console.log(num.constructor); // back to Number
Furthermore, if the only solution here is to add methods like .add(x), would I need to recreate a new class instance whenever a computation like .add(x) is done, or is there another more native way to add to the existing object's value.
If the below is the only workaround, I may stick to extending the built-in Number object:
class MyNum extends Number {
constructor (num = 0) {
super(num);
}
add(x) { return new MyNum(this.valueOf() + x) }
sub(x) { return new MyNum(this.valueOf() - x) }
mul(x) { return new MyNum(this.valueOf() * x) }
div(x) { return new MyNum(this.valueOf() / x) }
mod(x) { return new MyNum(this.valueOf() % x) }
get isEven() { return this.isInt && this % 2 === 0 }
get isOdd() { return this.isInt && this % 2 !== 0 }
}