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.setPrototypeOf
should 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, orclass
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
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?