Search code examples
javascriptprototypeprimitive

How do you extend the constructor for a builtin like Object or Number?


Suppose I'd like to make all Numbers have property foo after they are made, containing something like the double of their value, for example. I'd like to do

// extend Number constructor here.
console.log(5.foo); // outputs 10

How do you do it?


Solution

  • You don't extend the constructor, but rather the prototype, by defining a new property on it, with a "getter":

    Object.defineProperty(Number.prototype, 'foo', {
        get: function() { return this * 2; }
    });
    
    > 1.foo
      SyntaxError           // parser expected decimal part of number after dot
    > (1).foo
      2
    > 1..foo
      2
    > 1.0.foo
      2
    > Number(1).foo
      2
    > new Number(1).foo
      2
    > 1['foo']
      2
    > 1e0.foo               // exponential notation
      2
    > parseInt('1px').foo
      2
    > 0x1.foo               // hex
      2
    > 01.foo                // octal, disallowed in strict mode
      2
    > Math.PI.foo
      6.283185307179586
    > Infinity.foo
      Infinity
    > NaN.foo
      NaN
    

    Why does the first example 1.foo fail? The JS parser, once it sees the dot, expects a decimal portion. There's no way around that. So you'll have to content yourself with saying 1.0.foo.

    But 1.0 is a primitive not an object, right? Then, how can 1.0.foo possibly work? Because JavaScript will coerce (cast, or transform) primitives to objects when necessary. In this case the numeric value is coerced to a number object just long enough to compute the value of foo, after which the object is thrown away (by garbage collection).

    One might be tempted to also implement a setter, as in

    set: function(v) { this = v/2; }
    

    but of course this is invalid; we can't set this!! And there's no way to access the [[PrimitiveValue]] underlying the Number object to set it.

    I do not recommend the above, It's not considered best practice to extend built-in types in this way. This is best placed in the realm of exotica.