Numbers are primitives, so they don't inherit from Object
and are not instanceof
anything.
However, Javascript will box a number to a Number
object when you attempt to access a property (e.g. method), so that this property access is actually on the Number
object that was created on-the-fly. It is like you did:
console.log((new Number(num)).constructor.name);
console.log((new Number(num)).hasOwnProperty('prop'));
console.log((new Number(num)).prop):
prop
will be found in the prototype chain of the Number
object, but hasOwnProperty
-- as the name suggests -- does not look at the prototype chain, and so will not consider what you put on the Object.prototype
.
Note that this silent boxing does not happen when you don't attempt to access a property, so in num instanceof
the primitive is considered, not the Number
variant of it.
You can actually see the trace of that boxing by calling the toSource
method:
let num = 5;
console.log(num.toSource());
Fun fact: you can get this boxing also with a number literal -- it needs a second point to disambiguate from the decimal point:
console.log(1..toSource());
Specification of "boxing"
The EcmaScript specification defines this process in the section Property Accessors. The evaluation relies on
GetValue(propertyNameReference).
Which in turn, has this in its process definition:
If IsPropertyReference(V) is true, then
If HasPrimitiveBase(V) is true, then
Assert: In this case, base will never be undefined or null.
Set base to ! ToObject(base).
And finally ToObject
performs the actual wrapping.