0

I am trying to clarify the differences of both prototype and __proto__. Does __proto__ always point to the parent's prototype?

So Array.prototype would include methods like concat(), etc. and Array.__proto__ would point to the methods on the parent/base object of Array?

ddjk
  • 133
  • 2
  • 7
  • 3
    Best thing to do is to stop wondering about `__proto__` entirely, as it's a deprecated feature. Use `Object.getPrototypeOf()` instead. – Pointy Oct 12 '20 at 15:16
  • 1
    It's unclear what you mean by "parent", so I'll go out on a limb and say *No*. – Bergi Oct 12 '20 at 15:49

2 Answers2

2

TL:DR

__proto__ is a legacy feature that should generally be avoided MDN

What is __proto__

Simply put, __proto__ is just a propertyKey. And that's really all that you should see it as, because while there is a common behaviour among most builtin objects, It is by no means something that has to (or even should) behave in any specific manner.

Look at it as a regular getter/setter-pair

we can easily make any key behave in the same manner as __proto__:

const provingAPoint = {
  get thisIsANormalKey () { return Reflect.getPrototypeOf(this) },
  set thisIsANormalKey (proto) { Reflect.setPrototypeOf(this, proto) }
}

And that's basically all that __proto__ really is.

Always expect an object to differ from the default __proto__ behaviour

If you are recieving an object from some API you should not expect __proto__ to behave like it does in a default object. looking at the above example, it becomes clearer that it's not a reliable thing. We could for example do this:

Reflect.defineProperty(provingAPoint, '__proto__', {
  get: () => { throw new Error('you are not getting my prototype like this') },
  set: () => { throw new Error('you will not set my prototype like this') }
})

Now if someone tries to access this property, they will get an error. it's now also readonly and can't be changed or deleted.

Use the proper methods instead

The global objects Object and Reflect both have the static methods getPrototypeOf and setPrototypeOf (not going to go into detail about Reflect and it's differences). If you're going to manipulate the prototype chain, use these

The single valid use for __proto__ in todays Java/EcmaScript

There is one valid use that's suprisingly not well known. When you create an object literal, if you define a __proto__ property on it, if it's value is an object or null, the resulting object will use that value as it's prototype

// this can save you some of the annoyances of `Object.create(null, {...descriptors})`
const objectWithNullPrototype = {
  __proto__: null,
  propA: 'valueA',
  prop0: 'value0'
}

Object.getPrototypeOf(objectWithNullPrototype) // => `null`
// and again, don't extect any consistent behaviour of `__proto__` because:
objectWithNullPrototype.__proto__ // => `undefined`

About prototype

The prototype property on a function defines what the is inherited when constructing an object

In short

A constructors prototype property is equal to the prototype of the object it constructs. eg:

Object.getPrototypeOf(new Array(12)) === Array.prototype // => true
// NOTE: don't do this, use literals or `Object.create`
Object.getPrototypeOf(new Object()) === Object.prototype // => true
Object.getPrototypeOf(new Map()) === Map.prototype // => true

Java/EcmaScript is a prototype-based language

If you have any doubts on what this means, i highly recomend you google and read some articles about it, as misunderstanding (or not knowing) of the implications is a very common source of errors and confusion.

0

The subject in question __proto__ is deprecated and is, even when available, extremely slow and not recommended.

However, it is an accessor property1 which exposes the internal object through which it's accessed!

But if you read the following text by MDN, here then it tells about how and why it was implemented even tho it was never meant to be added.

Long story short, while it is a getter/setter and does not directly connect to the object but in almost any scenario, do NOT use it

Jacob Morris
  • 544
  • 4
  • 18
  • 1
    @Liam Wrong way round. `__proto__` is standardised (so that browsers that need to implement it for web-compatibility implement it consistently), but at the same time it is [explicitly deprecated in that standard](https://stackoverflow.com/a/36061819/1048572) in favour of modern `Object.get/setPrototopeOf`. – Bergi Oct 12 '20 at 15:51