2

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?

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.