2

See the below snippet.

let num = 3;
Object.prototype.prop = "something";
console.log(num instanceof Object); //false;
console.log(num.hasOwnProperty('prop')) //false

console.log(num.prop) //'something'

Can someone explain why num instanceof Object and num.hasOwnProperty('prop') returns false but still we can access the property of Object.prototype on num

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • I have an old [answer](https://stackoverflow.com/questions/21933120/what-is-the-difference-between-javascript-object-and-primitive-types/21933321#21933321) to a similar question, describing the differences, maybe it has some additional information. – Moritz Roessler May 18 '19 at 11:19

3 Answers3

4

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.

Community
  • 1
  • 1
trincot
  • 317,000
  • 35
  • 244
  • 286
  • @Maheer This can be helpful. [Primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) – Vivek May 18 '19 at 09:15
  • _"Javascript will box a number to a Number object when you attempt to access a property "_. I think this is answer to whole problem. Can you please provide any reference to that from specs. – Maheer Ali May 18 '19 at 09:28
  • Reference added. – trincot May 18 '19 at 09:40
  • It's also worth noting, that when using strict mode, `typeof this` in context of a `Number.prototype` function, will be "number" and not "object". See this [answer](https://stackoverflow.com/questions/21933120/what-is-the-difference-between-javascript-object-and-primitive-types/21933321#21933321) for reference – Moritz Roessler May 18 '19 at 11:15
0

Only actual objects can ever have their instanceof anything resolve to true. See the specification on instanceof, which points to HasInstance:

When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

  1. If V is not an object, return false.

Numbers aren't even instanceof Number:

console.log(1 instanceof Number);

Though, if you used new Number (which you shouldn't) and created an actual number object, it would work as you expect:

console.log(new Number(1) instanceof Number);
Community
  • 1
  • 1
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks for answer. But the problem is that why `num.prop` gets the value from `Object.prototype` – Maheer Ali May 18 '19 at 09:08
  • then what is `num`? Is it still an object or not? As according to Docs `Nearly all objects in JavaScript are instances of Object` – Vivek May 18 '19 at 09:09
0

hasOwnProperty on MDN:

The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).

Emphasis mine

The number inherits the property, so you can access it, but it isn't defined as a property on the number itself, which is why hasOwnProperty("prop") returns false.

And the reason that the instanceof fails is because it can only be used on explicit objects (constructed, or literals).

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79