Any reason why __proto__ is not a well known symbol?

# JD Isaacks (9 years ago)

I know ES2015 formally made the __proto__ property a way to access/set an object's internal [[Prototype]] property.

Is there any reason why this wasn't spec'd as a well known symbol such as @@__proto__. It just seems like it would line up well with other modifiers like @@iterator, @@species, etc.

Being that it was not formally spec'd it shouldn't have broke backwards compatibility either.

# Tab Atkins Jr. (9 years ago)

On Mon, Feb 15, 2016 at 8:34 PM, JD Isaacks <jd at jisaacks.com> wrote:

I know ES2015 formally made the __proto__ property a way to access/set an object's internal [[Prototype]] property.

Is there any reason why this wasn't spec'd as a well known symbol such as @@__proto__. It just seems like it would line up well with other modifiers like @@iterator, @@species, etc.

It was specified before symbols existed, and all implementations do it as a string property. If we were reinventing it today it would either be a symbol or something in the MOP, but are hands are tied by legacy.

Being that it was not formally spec'd it shouldn't have broke backwards compatibility either.

Backwards compat has nothing to do with specs, and everything to do with existing implementations. Multiple implementations agreed on proto, so our choice was either to leave it unstandardized or spec what the browsers did.

# Coroutines (9 years ago)

On Mon, Feb 15, 2016 at 8:51 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

It was specified before symbols existed, and all implementations do it as a string property. If we were reinventing it today it would either be a symbol or something in the MOP, but are hands are tied by legacy.

Being that it was not formally spec'd it shouldn't have broke backwards compatibility either.

Backwards compat has nothing to do with specs, and everything to do with existing implementations. Multiple implementations agreed on proto, so our choice was either to leave it unstandardized or spec what the browsers did.

Is there a migration to make it a Symbol in ES7? (ignorant question?)

# Kevin Smith (9 years ago)

Is there a migration to make it a Symbol in ES7? (ignorant question?)

Object.getPrototypeOf and Object.setPrototypeOf are the "no-dunder" ways to do it.

# JD Isaacks (9 years ago)

Object.getPrototypeOf and Object.setPrototypeOf are the "no-dunder" ways

to do it.

Not if you are trying to set in an object literal.

# Tab Atkins Jr. (9 years ago)

On Mon, Feb 15, 2016 at 9:14 PM, Coroutines <coroutines at gmail.com> wrote:

On Mon, Feb 15, 2016 at 8:51 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

It was specified before symbols existed, and all implementations do it as a string property. If we were reinventing it today it would either be a symbol or something in the MOP, but are hands are tied by legacy.

Being that it was not formally spec'd it shouldn't have broke backwards compatibility either.

Backwards compat has nothing to do with specs, and everything to do with existing implementations. Multiple implementations agreed on proto, so our choice was either to leave it unstandardized or spec what the browsers did.

Is there a migration to make it a Symbol in ES7? (ignorant question?)

There's a lot of code in the wild that uses proto and depends on it. We can't remove it until/unless that changes (it won't, at least not in the near future), and while we have proto, there's no reason to have anything else.

# Andrea Giammarchi (9 years ago)

Object.getPrototypeOf and Object.setPrototypeOf works everywhere, including null objects, as long as extension hasn't been prevented ( Objet.freeze, Object.seal or Object.preventExtension )

It's __proto__ accessor that indeed doesn't work as expected in null object, where it's always stored as key.

var dict = Object.create(null);
dict.__proto__ = [];

Object.keys(dict); // ["__proto__"]
dict instanceof Array; // false

Object.setPrototypeOf(dict, []);
dict instanceof Array; // true

However, if you want the key "__proto__" you can specify it at string at runtime {"__proto__": "this way"} or use Object.defineProperty(obj, "__proto__", {value: "any"})

# Dean Landolt (9 years ago)

On Tue, Feb 16, 2016 at 1:23 AM, Tab Atkins Jr. <jackalmage at gmail.com>

wrote:

On Mon, Feb 15, 2016 at 9:14 PM, Coroutines <coroutines at gmail.com> wrote:

On Mon, Feb 15, 2016 at 8:51 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

It was specified before symbols existed, and all implementations do it as a string property. If we were reinventing it today it would either be a symbol or something in the MOP, but are hands are tied by legacy.

Being that it was not formally spec'd it shouldn't have broke backwards compatibility either.

Backwards compat has nothing to do with specs, and everything to do with existing implementations. Multiple implementations agreed on proto, so our choice was either to leave it unstandardized or spec what the browsers did.

Is there a migration to make it a Symbol in ES7? (ignorant question?)

There's a lot of code in the wild that uses proto and depends on it. We can't remove it until/unless that changes (it won't, at least not in the near future), and while we have proto, there's no reason to have anything else.

Is it too late to remove support for dunder-proto strictly within module contexts? This might introduce a bit of a refactor hazard when pulling old code into modules, but it's only the static obj.__proto__ usage that has any effect so this can be handled pretty easily with linter warnings. Or it could be contextually reserved and throw an early exception.

# Andrea Giammarchi (9 years ago)

As much as Id love to see dunder-__proto__ burn away from any future specification, there are at least two use cases I do like in terms of simplification:

  1. to shortcut literals with enumerable, configurable, and writable own properties that extend known objects (or null) such {__proto__:null, key: 'value'} . This cannot be compared with the tedious Object.create(null, {key: {enumerable: true, writable: true, configurable: true, value: 'value'}})
  2. to explain inheritance through the console or to people in general, using it only as virtual-read-only reference to the inheritance chain

While the first point will be simplified a lot thanks to Object.getOwnPropertyDescriptors so that the literal form can be still used via Object.create(null, Object.getOwnPropertyDescriptors({key: 'value'})) the second point is still interesting but, like I've mentioned, usable as abstract concept too that doesn't need to be specd' as magic behavior.

Just my 2 cents

Best

# Coroutines (9 years ago)

On Tue, Feb 16, 2016 at 8:00 AM, Dean Landolt <dean at deanlandolt.com> wrote:

Is it too late to remove support for dunder-proto strictly within module contexts? This might introduce a bit of a refactor hazard when pulling old code into modules, but it's only the static obj.__proto__ usage that has any effect so this can be handled pretty easily with linter warnings. Or it could be contextually reserved and throw an early exception.

I dunno, it just seems odd to cement it forever in JS when you can even feature-test for it (vs using a Symbol). At some point I really just expect people to keep up with with things and not be a Python 2 lazy person :D I hope ES7 makes breaking changes all over the place :p

# Boris Zbarsky (9 years ago)

On 2/16/16 12:01 PM, Coroutines wrote:

I hope ES7 makes breaking changes all over the place

Do you also hope ES7 never ships in any web browsers?

Just checking, Boris

# Leo Balter (9 years ago)

For the sake of consistency and compatibility, instead of the following example:

{__proto__:null, key: 'value'}

Let this key be represented by a Symbol.proto or Symbol.toPrototype. This would work fine to avoid using Object.create getting descriptors or along Object.assign.

unless TC39 want to represent other Symbols within the __ notation, __proto__ should be left alone and die in the first moment it's possible.

# Allen Wirfs-Brock (9 years ago)

On Feb 16, 2016, at 8:00 AM, Dean Landolt <dean at deanlandolt.com <mailto:dean at deanlandolt.com>> wrote:

s it too late to remove support for dunder-proto strictly within module contexts? This might introduce a bit of a refactor hazard when pulling old code into modules, but it's only the static obj.__proto__ usage that has any effect so this can be handled pretty easily with linter warnings. Or it could be contextually reserved and throw an early exception.

dunder proto as built-in property of Object.prototype is mode/syntactic context independent. It can be restricted in that manner.

On the other hand, the meaning of dunder-proto within an object literal is specified [1] as a syntactic form. So, in theory, its use could be restricted to specific syntactic contexts such as strict mode or not in a Module. ES2015 did not apply any such restrictions and given that strict mode and dunder-proto has co-existed in browsers since ES5 it’s unlike the we could purge it from strict mode. Making it illegal in Modules might still be feasible. It would probably take some some strong advocation within TC39 to make it happen.

Allen

[1] tc39.github.io/ecma262/#sec-proto-property-names-in-object-initializers tc39.github.io/ecma262/#sec-__proto__-property-names-in-object-initializers

# Bergi (9 years ago)

Andrea Giammarchi wrote:

As much as Id love to see dunder-__proto__ burn away from any future specification,

Before doing that, we should burn it away from everyones code :-)

there are at least two use cases I do like in terms of simplification:

1. to shortcut literals with enumerable, configurable, and writable own
properties that extend known objects (or null) such `{__proto__:null, key:
'value'}` . This cannot be compared with the tedious `Object.create(null,
{key: {enumerable: true, writable: true, configurable: true, value:
'value'}})`

The much simpler solution to that would be Object.setPrototypeOf({key: 'value'}, null) (which also returns the object). Admittedly, putting the prototype in the end is a bit awkward, and __proto__ in a literal probably simplifies creation optimisations. The way to overcome this would be to promote the prototype <| operator, which I would love to see in ES8. Anyone up for making an up-to-date proposal?

2. to explain inheritance through the console or to people in general,
using it only as virtual-read-only reference to the inheritance chain

I wholeheartedly recommend to use the term [[prototype]] (in italics or color) for this, and call it out as what it is: an internal property. Don't teach people that __proto__ is a magical property - it is not (causing confusion); and they only will start or continue using it in new code. Even in code examples, or simple demonstrations, use console.log(x, Object.getPrototypeOf(x)) over console.log(x, x.__proto__).

, Bergi

PS: Ceterum censeo proto esse delendum :-)

# Andrea Giammarchi (9 years ago)

You break an open door and I was the one proposing setPrototypeOf and to kill __proto__ long time ago but about this:

Don't teach people that __proto__ is a magical property - it is not (causing confusion); and they only will start or continue using it in new code.

I'm afraid my recent book is the only one I know that avoided dunder-proto. Most other articles/books about "modern JS" all use and/or describe __proto__

So we need people to stop using it, and modules would be a great opportunity to at least warn the community, and we need to stop talking about it in modern published online and offline books.

Best