What is in Object.__proto__?
Asked Answered
I

3

12

In Google Chrom's javascript, objects have a property named __proto__ that points to their prototype (or parent) object.

var foo = {};
console.log(foo.__proto__ === Object.prototype);    //returns true

However, this is not true for the Object object.

console.log(Object.__proto__ === Object.prototype);    //returns false

The Object.__proto__ property appears to be an empty method

> console.log(Object.__proto__.toString());
function () {}

Beyond serving as a warning story about relying on javascript features that start outside standard bodies -- what is the Object.__proto__ function?

Izzo answered 1/12, 2016 at 21:41 Comment(8)
Object.__proto__ === Function.prototype ...Object is a function. typeof Object === "function"Anticipate
Have you read through this document? It might clear up some things. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Capping
...and __proto__ was added to ECMAScript 6.Anticipate
...and the reason Function.prototype appears to be an empty function is that many of the prototypes of the built-in constructors are actually an instance of the object they construct. For example, Array.isArray(Array.prototype); // true (Or maybe not quite an instance, but they have some relationship back to the constructor.)Anticipate
@squint, ...and Function.__proto__===Function.prototypeCalycle
Ah, thank you @squint. Object.__proto__ === Function.prototype being true and Object.__proto__.__proto__ === Object.prototype being true cleared this up for me. I've always assumed Object and Function were at the same hierarchy level, and that Object's prototype was Object.prototype. If you wanted to add some version of your comment as an answer I'm happy to mark it as best.Izzo
You're welcome. I'm too tired to put together a decent answer, so feel free to gather together what I wrote and whatever else you've figured out, and post an answer instead.Anticipate
Thanks again @squint -- done and below.Izzo
I
4

Based on squint's comments above, I've been able to get to the bottom of this. My unstated, incorrect (and 10+ year) assumption was that the global Object helper object's prototype object was also the top level "prototype of prototypes" at the top/end of javascript's prototype chain. This is not true.

The Object helper object and the Function helper object both have the same parent prototype-object

console.log( Object.__proto__ === Function.__proto__ );    //true

So, the reason Object.__proto__ points to an empty function is -- that empty function is its prototype object for the Object object. If you want to get to the prototype of prototypes from Object (without using .prototype), you need to dig back a bit further.

console.log( Object.__proto__.__proto__ === Object.prototype );         //true

I also put together a quick diagram that maps out the real prototypes of a few of Javascript's lower level helper/constructor objects.

enter image description here

Finally -- I also also discovered Google Chrome has implemented the Reflect object, which includes a getPrototypeOf method, which appears to be the same as the Object.getPrototypeOf method.

Izzo answered 2/12, 2016 at 17:26 Comment(5)
Re: down-voters -- if something above is incorrect, please let me know. If it's correct but you dislike my point of view -- I guess I'll live with the downvotes ;)Izzo
I think you're right, but the graph is confusing because I'd expect the arrows to be pointing the other direction (the direction of inheritance). And this sentence is confusing: "The Object helper object shares its prototype with the Function helper object." The phrasing is vague. I can't tell when you're talking about the constructor functions, their .prototype or the object from which they inherit (which is accessible via __proto__). So that may be part of the reason for the DVs.Anticipate
The getPrototypeOf is new with the Reflect object, but it has been around for quite a while via Object.getPrototypeOf. At least I think they're the same. Haven't really looked too much at Reflect yet. EDIT: I see on the docs that they are indeed the same. Good.Anticipate
Changed the wording to be clearer, and updated the diagram to have the arrows pointing back towards the top of the hierarchy. Also, FWIW, most docs lack of clarity about the .prototype property and an object's true "parent object prototype" are what led to this question in the first place. Thanks again for the help @squint!Izzo
How does Array instanceof Object allow true if instanceof checks the prototype chain? In the chart Object (helper) is not in the prototype chain of Array (helper)Debag
P
10

The top of the object graph is formed to maintain as much consistency with the expectations set elsewhere in the spec.

Necessarily, there comes a point where normal object linkages cannot be used because you "run out of objects".

A basic understanding of JavaScript leads us to expect the [[Prototype]] of Object to be the prototype property of the function used to create the Object function-object.

We expect Functions to be created using the Function function-object, so...

Object.__proto__ === Function.prototype

Because we are at the top of the object graph and want to maintain consistency of expected behavior we configure the [[Prototype]] of Function to be Function.prototype.

Function.__proto__ === Function.prototype

Thus ensuring Function instanceof Function === true.

We can show that Function.prototype is a special function-object because:

Function.prototype.prototype === undefined

...and every user-defined function (other than fat-arrows) has an object on its prototype property.

Because of all the above:

Object.__proto__ === Function.__proto__

This may might look odd, but as previously noted, at the top of the object graph we have a limited set of candidate objects to point to.

TC-39 now needed to identify what the [[Prototype]] of the [[Prototype]] of Object was. Per the above we know that the [[Prototype]] of Object is Function.prototype.

In some sense we are now above Function.prototype in the object graph, so a special Object instance (the "prototype object") was chosen to be this value.

This means that the top of every prototype chain can be conveniently tied up with Object.prototype.

This of course, also meets the desireable requirement that everything "is an object".

Object.__proto__.__proto__ === Object.prototype 

At this point we need to complete the object graph, so we set the [[Prototype]] of Object.prototype to be null.

Object.__proto__.__proto__.__proto__ === null
Plusch answered 1/12, 2016 at 21:56 Comment(5)
Useful information @BenAston -- thank you! but I'm not sure the Object.__proto__ information is correct? Object.__proto__.toString() returns "function () {}" -- i.e. an empty function, not a [native code] function (Chrome, OS X El Cap)? Re: outside standard bodies, my statement/snark was unclear. It's my understanding proto was implemented in browsers despite it not being a part of an ES standard, and was only recently incorporated into the ES6 standard.Izzo
The rendering of Object.__proto__.toString() will depend on the version of your browser. Also: you want toString to print out the C++ source code? If you don't believe me: tell me what user-land function created the built-in Object function-object?Plusch
The reason I'm not sure your description is 100% accurate is, if I log a function with native code in Chrome's browser, (or use the toString method), I get something that mentions the [native code] (function split() { [native code] }. However, when Chrome (or .toString) renders the Object.__proto__ object, it does not include the native code and looks like an empty user land function (function() {})Izzo
Downvoter, please explain! If I'm wrong, please explain how so I can learn from my mistake.Plusch
Down-voted for the incorrect information about "Native Code" functions. Down-vote removed now that that's gone.Izzo
I
4

Based on squint's comments above, I've been able to get to the bottom of this. My unstated, incorrect (and 10+ year) assumption was that the global Object helper object's prototype object was also the top level "prototype of prototypes" at the top/end of javascript's prototype chain. This is not true.

The Object helper object and the Function helper object both have the same parent prototype-object

console.log( Object.__proto__ === Function.__proto__ );    //true

So, the reason Object.__proto__ points to an empty function is -- that empty function is its prototype object for the Object object. If you want to get to the prototype of prototypes from Object (without using .prototype), you need to dig back a bit further.

console.log( Object.__proto__.__proto__ === Object.prototype );         //true

I also put together a quick diagram that maps out the real prototypes of a few of Javascript's lower level helper/constructor objects.

enter image description here

Finally -- I also also discovered Google Chrome has implemented the Reflect object, which includes a getPrototypeOf method, which appears to be the same as the Object.getPrototypeOf method.

Izzo answered 2/12, 2016 at 17:26 Comment(5)
Re: down-voters -- if something above is incorrect, please let me know. If it's correct but you dislike my point of view -- I guess I'll live with the downvotes ;)Izzo
I think you're right, but the graph is confusing because I'd expect the arrows to be pointing the other direction (the direction of inheritance). And this sentence is confusing: "The Object helper object shares its prototype with the Function helper object." The phrasing is vague. I can't tell when you're talking about the constructor functions, their .prototype or the object from which they inherit (which is accessible via __proto__). So that may be part of the reason for the DVs.Anticipate
The getPrototypeOf is new with the Reflect object, but it has been around for quite a while via Object.getPrototypeOf. At least I think they're the same. Haven't really looked too much at Reflect yet. EDIT: I see on the docs that they are indeed the same. Good.Anticipate
Changed the wording to be clearer, and updated the diagram to have the arrows pointing back towards the top of the hierarchy. Also, FWIW, most docs lack of clarity about the .prototype property and an object's true "parent object prototype" are what led to this question in the first place. Thanks again for the help @squint!Izzo
How does Array instanceof Object allow true if instanceof checks the prototype chain? In the chart Object (helper) is not in the prototype chain of Array (helper)Debag
C
1

Alan Storm's answer seems could use the following modifications:

  1. Delete the 3rd node of 2nd column of the digram, which is misleading: Array.__proto__ is not the "Array Object's Prototype" but the same as Function.__proto__ (Array.__proto__ === Function.__proto__ is true)
  2. Make Array Contructor point to it's true prototype, which is Function.__proto__ The diagram should look like something like this: https://i.sstatic.net/f1Fko.png
Curch answered 23/7, 2022 at 8:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.