getify / You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.
Other
179.37k stars 33.48k forks source link

"es6 & beyond": Setting [[Prototype]] section needs to be updated #380

Closed rwaldron closed 9 years ago

rwaldron commented 9 years ago

Object.setPrototypeOf(target, proto) is the "ES6 way" to set the prototype of an object.

__proto__ was banished to Annex B:

getify commented 9 years ago

Agreed I should most definitely cover Object.setPrototypeOf(..) as an option.

But I think it's up for debate whether that's truly the preferred way (despite being the endorsed "ES6 way"). One man's "banished" is another man's "thank god they finally standardized it so IE would put it in".


My bias for preferring the __proto__ in object literals (only there, never as a property!) is because I practice classless-object delegation patterns (what I call OLOO in the this & Object Prototypes book in this series), usually with object literals, and ES6 object literals also let me have all the nice ES6 sugars.

Listing __proto__ in the literal is ugly, no doubt. But it's slightly less ugly, IMO, than a separate line of code or wrapping call, both of which invert the syntactic ordering.

IOW, comparing:

var P = { .. };
var C = { __proto__: P, .. }

to:

var P = { .. };
var C = { .. };
Object.setPrototypeOf( C, P );

or:

var P = { .. };
var C = Object.setProtototypeOf( { .. }, P );

IMO, it's nicer that the __proto__ can be specified at the top of the object literal, instead of putting the relationship to P at the bottom after the whole C definition.


Anyway, my opinion/preference notwithstanding, I'll find a way to fairly cover Object.setPrototypeOf(..) that presents that as viable, and make it clear that __proto__ is "banished". ;-)

rwaldron commented 9 years ago

Anyway, my opinion/preference notwithstanding, I'll find a way to fairly cover Object.setPrototypeOf(..) that presents that as viable, and make it clear that proto is "banished". ;-)

That's all I can ask for :)

getify commented 9 years ago

Thanks for the suggestions. Fairer treatment? :)

gihrig commented 9 years ago

While Object.setPrototypeOf(..) may be the "ES6 way", it is, unfortunately, not well supported as of May 2015. By "not well supported", I'm referring to no support in Safari, Traceur, Babel or Closure. https://kangax.github.io/compat-table/es6/

This, unfortunately, makes Object.setPrototypeOf(..) unusable in production, for now. Not sure what's the bias against It, but it would be helpful if "This and Object prototypes ch 6 "Nicer Syntax" pg 136" would point this out.

Further, while __proto__ may be 'controversial', it works today, and thanks to standardization, is expected to work well into the future. For these reasons, I would say that "ES6 and Beyond" 'narrowly endorsing' __proto__ (pg 39) is probably still too harsh.

I don't know why the transpilers don't support Object.setPrototypeOf(..), but until they do, it's just not a viable alternative IMO.

getify commented 9 years ago

The only thing the transpilers could do is convert Object.setPrototypeOf(x,y) to x.__proto__ = y, which would obviously be super easy for them to do. I don't know why they don't, but my guess is they don't want to transpile to something that doesn't actually work in all ES5 browsers (like all of IE9 and IE10, which don't have __proto__). Doing so is like a false sense of confidence. Or they could do so but throw warnings at you about IE9 and IE10, I guess.

This is one of those (thankfully few) sticky issues where it can't be transpiled if it doesn't already exist. Basically, they just throw their hands up and say, "there's nothing we can do about it."


As for the books...

gihrig commented 9 years ago

Hey Kyle!

The best change I could recommend would be to make clear the difficulties surrounding Object.SetPrototypeOf() and proto, as you have clearly spelled out here.

Thanks for the instant response. And thanks for the YDKJS series. In my experience, it’s more than living up to the promise of Preface:Mission “You don’t really know JavaScript yet, but if you dig into this series, you will.” I’d say it's “Mission Accomplished”!