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?
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.