1

In Browser there are some Global-Objects pre-built (Objects, String, Number, Date, etc). Mother of all such global-objects is "Object". As, this Object is the prototype of nearly all of the data-types present in JS (except only 2 - null and undefined).

Now, we move up after creating any variable of any data-type, we'll use __proto__ to climb up the chain. But, when we react the "Object", the __proto__ points to null and "prototype-chain" has an ending!

Till now I thought prototype and __proto__ are one and the same. Today, I went and found, that in the Global-Object, while __proto__ points to null,[[prototype]] (inside get proto & set proto) consists of heaps of other values.

Can someone differentiate to me, what exactly is the difference between __proto__ and [[prototype]] and why the values inside both are completely different? While I thought both things are 1 and the same!

enter image description here

I also read this: Difference between __proto__ and [[ Prototype ]] in javascript but got more confused as it says __proto__ === [[prototype]] but then says something of internal-slot? Now, can I get a simple clear answer?

Also, if the __proto__ is null, how then get __proto__ fetch any result? --isn't this absurd? It will fetch result, only if the any value is there, and not null.

Deadpool
  • 7,811
  • 9
  • 44
  • 88
  • *"Till now I thought `prototype` and `__proto__` are one and the same."* Please clarify that. Do you mean you thought `Object.prototype` and `Object.__proto__` were the same? – T.J. Crowder Feb 05 '22 at 10:10
  • @T.J.Crowder - Yes for anything, like `Array.__proto__` and `Array's [[prototype]]`, or for that matter same for anything like Date, String, Promise, Number, etc. – Deadpool Feb 05 '22 at 10:12
  • How about this answer? https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript – saba silagadze Feb 05 '22 at 10:13
  • @Deadpool - That doesn't answer my question. Are you talking about `Array.prototype` and `Array.__proto__`? (**Not** `[[Prototype]]`) – T.J. Crowder Feb 05 '22 at 10:13
  • @T.J.Crowder - I think now there are 3 items - `Array.prototype`, `Array.__proto__`, and `[[prototype]]`. I thought all 3 were just the same. – Deadpool Feb 05 '22 at 10:15
  • The `[[prototype]]` you mark in the screen shot is not of the main object, but of the setter **function**. That is a different object! – trincot Feb 05 '22 at 10:16
  • 1
    https://stackoverflow.com/a/572996/1169519 – Teemu Feb 05 '22 at 10:17
  • 1
    @Deadpool - Correct, there are three things. And no, they aren't all the same. – T.J. Crowder Feb 05 '22 at 10:17
  • @trincot - But, prototype always refers to `next object that is parent and linked`, There is no setter object in this `prototype chain`. For eg, `let obj1 = new Object()`. obj1.__proto__ points to Global-Object, obj1.__proto__.__proto__ points to null. Where is *setter function* in this chain? – Deadpool Feb 05 '22 at 10:18
  • 1
    It is there: `set __proto__: f` .... the `f` tells you this `__proto__` property is a *function* and the `set` keyword indicates that it is a *setter* (look up getters & setters). So as long as the setter is not **called**, we are looking at a function. And functions are objects with their own properties that have nothing to do with the object on which they are a property. Although we use getters and setters as if they are plain properties, they are not: they are implemented as functions (a getter and a setter). In the screenshot you see the properties of those **functions**, not of the proto. – trincot Feb 05 '22 at 10:22

2 Answers2

1

In a comment you've said:

I think now there are 3 items - Array.prototype, Array.__proto__, and [[prototype]]. I thought all 3 were just the same.

([[Prototype]] is usually capitalized.)

That's the fundamental misunderstanding (that and looking at the wrong part of the console output; more below). They aren't. Here's what they are:

  1. [[Prototype]] is the name of the internal field of an object that says what that object's prototype is.
  2. __proto__ is an accessor property defined by Object.prototype that exposes the [[Prototype]] internal field. As I've told you before, it's deprecated. Use Object.getPrototypeOf and (if you can't avoid it) Object.setPrototypeOf.
  3. SomeConstructorFunction.prototype is a property on SomeConstructorFunction that refers to an object. If you create an object via new SomeConstructorFunction (or an equivalent operation), the object that SomeConstructorFunction.prototype refers to is set as the [[Prototype]] of the new object.

See also the answers to this question.

In Browser there are some Global-Objects pre-built (Objects, String, Number, Date, etc). Mother of all such global-objects is "Object". As, this Object is the prototype of nearly all of the data-types present in JS (except only 2 - null and undefined).

No, Object is a function. Object.prototype is the mother of all objects — except the ones it isn't, because it's possible for an object not to inherit from it (or indeed, from anything). Object.create(null) creates an object with no prototype object.

Can someone differentiate to me, what exactly is the difference between __proto__ and [[prototype]] and why the values inside both are completely different?

They aren't (but keep reading). In the picture you've shown, you're looking at [[Prototype]] on a function, the setter of the __proto__ accessor property. You're not looking at [[Prototype]] on the same thing you're looking at __proto__ on.

In your picture you're basically looking at Object.prototype (because you're looking at __proto__ on the result of new Object). Chrome's devtools don't show the [[Prototype]] internal field of Object.prototype (surprisingly), but it they did it would be null per specification.

Let's instead look at a simple object:

devtools screenshot of the text below

>  const obj1 = {example: "x"};
<- undefined
>  obj1
<- {example: 'x'}
      example: "x"
      [[Prototype]]: Object
>  Object.getPrototypeOf(obj1) === Object.prototype
<- true
>  Object.getPrototypeOf(obj1) === obj1.__proto__
<- true
>  obj1.prototype
<- undefined

(One part of that which could be confusing is where is says [[Prototype]]: Object. The devtools show the name of the constructor for an object. The [[Prototype]] of the object is the object referenced by Object.prototype, not the Object constructor itself.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

In the screenshot you shared, you compare two things that are unrelated.

The first box shows the value you get from accessing __proto__. It is indeed null. But realise that this value is retrieved by calling the getter. __proto__ is not a plain property, it is implemented using a getter and setter. This means that when you write:

var a = x.__proto__;

... a function is called. This is the get __proto__ function. This function is a method that is defined in the prototype chain of x (it is actually defined on Object.prototype).

Similarly if you write:

x.__proto__ = a;

...a function is called. This is the set __proto__ function.

The second box in your screenshot shows the properties of this set __proto__ function object. Remember that functions are objects too. And that object has little to do with the main object of your screenshot.

You can also access the definitions of these getter and setter functions with the following script:

let descriptor = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");

console.log(descriptor);
trincot
  • 317,000
  • 35
  • 244
  • 286