Thursday, May 16, 2013

Object.setPrototypeOf(O, proto) IS in ES6

This one is a short one, just to confirm that finally Object.setPrototypeOf(obj, proto) made it into ES6.
The section 15.2.3.2 speaks clearly:
15.2.3.2 Object.setPrototypeOf ( O, proto )
When the setPrototypeOf function is called with arguments O and proto, the following steps are taken:
  1. If Type(O) is not Object, then throw a TypeError exception.
  2. If Type(proto) is neither Object or Null, then throw a TypeError exception.
  3. Let status be the result of calling the [[SetInheritance]] internal method of O with argument proto.
  4. ReturnIfAbrupt(status).
  5. If status is false, then throw a TypeError exception.
  6. Return O.
Without going into details, the most basic polyfill woud be like this:
(function(O,s){
O[s]||(O[s]=function(o,p){o.__proto__=p;return o})
}(Object,'setPrototypeOf'));
If you want to go into details, the full reliable polyfill is hard to write down due all inconsistencies across JS engines out there where the __proto__ setter cannot be reused which means it's not possible to trust this magic over objects created from null.
All you need to do is forget __proto__ and use the suggested polyfill until the day __proto__ can simply disappear from those specs pages.
Enjoy!
This is a full polyfill with some extra info you might want to analyze, whenever ployfill is strictly true or false.

3 comments:

medikoo said...

Andrea, big thanks for you activity to give this issue such attention.

It's totally awesome we finally have Object.setPrototypeOf instead of ugly obj.__proto__

Sebastian said...

I don't get why the hate of __proto__, and want to remove it from the spec. I find it clear and easy to use. I thought it was going to be standardised in ES6. Personally I prefer o.__proto__ = x than Object.setPrototypeOf(o, x)

Andrea Giammarchi said...

no Sebastian, you don't prefer that, trust me.

You don't want a property name able to destroy the nature of an object in a loop because you didn't filter that.

You don't want to be unable to use dictionaries in a clean way where every property is a own one and no magic is generated by any other.

You don't want to pollute the Object.prototype with proprietary experiments only because of early, and broken, implementations, plus you don't want to standardize a completely broken/messed up property you cannot polyfill across already broken implementations.