Reputation: 46128
I'm trying to inherit from Number to override the toString method to output fixed decimal points when toString is called:
function FixedNumber(value) {
Number.call(this, value);
}
util.inherits(FixedNumber, Number);
FixedNumber.prototype.toString = function() {
return this.toFixed(3);
}
var n = new FixedNumber(5);
var s = n.toString();
Unfortunately, this doesn't work. I get the following exception:
TypeError: Number.prototype.valueOf is not generic
at FixedNumber.valueOf (native)
at FixedNumber.toFixed (native)
at FixedNumber.toString (repl:2:13)
at repl:1:3
at REPLServer.self.eval (repl.js:110:21)
at repl.js:249:20
at REPLServer.self.eval (repl.js:122:7)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
What have I done wrong, and how do I do what I want?
Upvotes: 2
Views: 400
Reputation: 16020
When Number
is called as a function (as what happens when you use call
on it), it does not act like an "ordinary" constructor -- instead, it simply converts the argument to a number.
15.7.1.1 Number ( [ value ] )
Returns a Number value (not a Number object) computed by ToNumber(value) if value was supplied, else returns +0.
Other than that, it does nothing. What you're essentially returning is a plain object with a prototype based on Number.prototype
-- the internal property that stores the actual number is not set.
Since the object that's returned is not a Number object, it fails because Number.prototype.toString
is not generic, which means that it can only be used on actual Number objects or primitives. Even if it didn't throw an error, it'd probably return "NaN"
as that's the default if not set.
There's really no "clean" way of doing this right now, though this will be possible with ES6 by subclassing native constructors.
Though this is sort of a hack and rather messy, you could do something like:
function FixedNumber(num) {
this.toString = function () {
return num.toFixed(3);
};
// implement the rest of Number.prototype as instance methods
}
// make instanceof return true
FixedNumber.prototype = Object.create(Number.prototype);
It's not really feasible to place these methods on the prototype, as there is no access to the actual number stored.
Upvotes: 4