setPrototypeOf vs obj.__proto__ assignment

# John Barton (11 years ago)

I was surprised to discover that in chrome at least this is valid:

  var obj = {};
  obj.__proto__ = undefined;

but this throws

   Object.setPrototypeOf(obj, undefined);

Is it intended?

# Allen Wirfs-Brock (11 years ago)

On Apr 4, 2014, at 10:22 AM, John Barton wrote:

I was surprised to discover that in chrome at least this is valid:

  var obj = {};
  obj.__proto__ = undefined;

but this throws

   Object.setPrototypeOf(obj, undefined);

Is it intended?

Yes, see the spec at people.mozilla.org/~jorendorff/es6-draft.html#sec-set-object.prototype.proto

It's that way because that's how __proto__ has always worked.

__proto__ is there for legacy compatibility. setPrototypeOf should be preferred for new code

# Andrea Giammarchi (11 years ago)

you probably meant this link too? people.mozilla.org/~jorendorff/es6-draft.html#sec-object.setprototypeof

  1. If Type(proto) is neither Object nor Null, then throw a TypeError exception.
# Andreas Rossberg (11 years ago)

On 4 April 2014 19:49, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

__proto__ is there for legacy compatibility. setPrototypeOf should be preferred for new code

For new code, neither should be used.

# David Bruant (11 years ago)

yup.

For new code, in most practical cases, people can use class&extend including to subclass Array and Date where __proto__ used to be the only way.

# Axel Rauschmayer (11 years ago)

I like __proto__ in object literals, as a nicer Object.create(). In that case, __proto__ is “the new <| operator” and really quite different from __proto__ as a getter and a setter.

I have two uses for it:

  • Dict pattern { __proto__: null, ... }
  • To explain prototype chains to beginners (=> not something that would be used in production code).

If ECMAScript 6 didn’t support classes and subclassing, it would help with subclassing, too.

# John Barton (11 years ago)

The context for my question was Tom van Cutsem's excellent Proxy shim, tvcutsem/harmony-reflect, which uses __proto__ assignment to shim Object.setPrototypeOf. In developing Proxy code, objects and not classes are relevant. Directly manipulating the __proto__ is vastly superior to any solution based on es6 classes or our unfortunate friend Object.create().

# K. Gadd (11 years ago)

Is my understanding correct that proto/setPrototypeOf are still required if you want to do things like that with instances of Function? Or did Function's constructor finally get patched to let you set a prototype?

# Andrea Giammarchi (11 years ago)

nope, if you have a dict and you use proto nothing should happen, that's why Object.setPrototypeOf is suggested: it's more powerful + it does not show up in getOwnPropertyNames as 'proto' does so it's shenanigans and errors prone.

proto is not even more elegant than Object.create(null) plus you can use a piece of code that fits in a tweet to simplify its equivalent usage when meant.

var o = Object.setPrototypeOf(
  {
    // your literal object
  },
  Object.prototype // your inherited proto
);

wanna simplify that ? here just an example


*var* O*=function*(O,s){s*=*O.setPrototypeOf*||function*(o,p){o.__proto__*=*
p;*return* o};*return* *function*(p,o){*return* o*?*s(o,p)*:*p*||*s({},p)}}(
Object);


var obj = O(null, {

  // your literal Object

});


// same as

var obj = O(

Array.prototype,

{}

);

Most __proto__ support is completely broken these days when it comes to dictionaries ... since {__proto__:null}.__proto__ still shows up and the only fix is to delete Object.prototype.__proto__ where possible, or reuse its setter so simulate Object.setPrototypeOf when it's not poisoned.

All this has been discussed for years now ... it's surprising it's still not clear why the explicit Object.setPrototypeOf is the preferred choice.

It feels like everyone uses __proto__ on daily basis while ES6 promotes classes ... so either __proto__ is not a real world use case, or class landed for no reason, IMO.

# John Barton (11 years ago)

On Mon, Apr 7, 2014 at 10:51 AM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

..

It feels like everyone uses __proto__ on daily basis while ES6 promotes classes ... so either __proto__ is not a real world use case, or class landed for no reason, IMO.

You are correct, lots of code uses 'proto', but your conclusions based on this make no sense. ES6 has nothing to say about daily use until it ships in all relevant platforms, and the current count is zero. Moreover, on platforms without setPrototypeOf(), it's advantages are not relevant. jjb

# Andrea Giammarchi (11 years ago)

that's why it's the preferred choice ... otherwise we keep promoting and trapping developers behind a broken pattern.

If we keep saying "just use __proto__" code won't ever migrate but it's been discussed that in some case __proto__ is a very problematic keyword.

nashorn even implemented it with the infamous dual intent, obj["__proto__"] vs obj.__proto__ , thanks gosh duktape didn't implement __proto__ at all and it promotes pure ES5.1 approach via Object.create and no hot-swap problems.

# Andrea Giammarchi (11 years ago)

just for topic and documentation sake ...

On Mon, Apr 7, 2014 at 11:02 AM, John Barton <johnjbarton at google.com> wrote:

on platforms without setPrototypeOf(), it's advantages are not relevant. jjb

this works in Firefox since quite a while, and probably some other engine that supports __proto__ as non poisoned and configurable as every other Object.prototype is:

Object.setPrototypeOf || (
  Object.setPrototypeOf = function(set){
    delete Object.prototype.__proto__;
    return function setPrototypeOf(o, p) {
      set.call(o, p);
      return o;
    };
  }(
    Object.getOwnPropertyDescriptor(
      Object.prototype, '__proto__'
    ).set
  )
);

Best