setPrototypeOf vs obj.__proto__ assignment
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
you probably meant this link too? people.mozilla.org/~jorendorff/es6-draft.html#sec-object.setprototypeof
- If Type(proto) is neither Object nor Null, then throw a TypeError exception.
On 4 April 2014 19:49, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
__proto__is there for legacy compatibility.setPrototypeOfshould be preferred for new code
For new code, neither should be used.
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.
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.
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().
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?
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.
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, orclasslanded 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
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.
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
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?
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? jjb -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140404/0eb759b6/attachment.html>