My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, January 17, 2013

JS __proto__ Shenanigans

I can't believe it, every time some cool pattern comes into games, __proto__ makes everything pointless, in a trusted meaning of a generic property!

Previously, in Internet Explorer

One of the biggest and most known WTFs in IE is the fact that Object.prototype properties are not enumerable.
While is possible to define such properties in ES5, this is the classic good old IE only scenario we all remember:
for(var key in {toString:"whatever"}) {
  alert(key); // never in IE
}
As simple as that, all native properties in the main prototype were considered {toString:true}.propertyIsEnumerable("toString") === false because indeed, these were not enumerating (just in case: enumerable properties are those that should show up in a for/in loop)

The Same Mistake With __proto__ If Not Worse

That's correct, the moment you play with this property name things start falling a part same old IE way or even worst.
alert(
  {__proto__:"whatever"}.
    propertyIsEnumerable(
      "__proto__"
    ) // this is false !!!
);
Not only enumerability, but also the hasOwnProperty(key) is gone!
var o = {};
o.__proto__ = 123;
o.hasOwnProperty("__proto__");
// false !!!

Do Not Use Such Mistake

Even if part of new specs, __proto__ is showing off all its anti pattern problems we all laughed about when it was IE only.
As a property, we should not have any special case, able of these kind of problems, while we should all keep using Object.statics() function that works internally, rather than on property name level.
So now you know ;)

3 comments:

Anonymous said...

__proto__ is a getter/setter so you shouldn't be able to make it own just by doing:

o.__proto__ = 123;

.. asit just invokes underlying getter

Different story is if you do:

Object.defineProperty(o, '__proto__', { value: 123 });
o.hasOwnProperty('__proto__'); // true (at least in chrome)

Still __proto__ is very special, and I believe no engine should allow to set or define it as regular property.

Personally I would prefer TC39 to abandon __proto__ and define Object.setPrototypeOf, but due to not exactly clear for me reasons I heard that's a no go.

Andrea Giammarchi said...

you made my points because all I am saying is that is too special and it inevitably leads to shenanigans indeed :)

I agree about setPrototypeOf 100%

tobi said...

+1 for setPrototypeOf