Object.getPrototypeOf

Historically one JavaScript property that’s seen a lot of use (mostly due to its convenience) is that of __proto__. It’s a quick-and-dirty way of accessing the original prototype property of the object’s constructor function. For example, the following is true:

"test".__proto__ === String.prototype
// Another alternative, not using __proto__
// Only works when constructor isn't changed
"test".constructor.prototype === String.prototype

This feature has been codified in the upcoming ECMAScript 3.1 specification as a new method: Object.getPrototypeOf(object) (and is implemented in the latest Firefox nightlies).

So how can we make use of this, now standardized, functionality?

instanceOf

If you wish you could implement your own version of the instanceof operator, using pure JavaScript.

In the above code we use Object.getPrototypeOf(this) to tap in to the original, inherited, kick method. Since we have since overridden the method we don’t have direct access to it, but using getPrototypeOf we can capture, and utilize, it again.

Cross-Browser Implementation

The obvious question now becomes: How do we begin using Object.getPrototypeOf today if most browsers don’t have it implemented yet? In the meantime we can use something like the following code for some form of compatibility:

While it’s not 100% spot-on (since the .constructor property is mutable on any object – it’s fully possible that it could’ve been manipulated by the user at some point) the above code should serve as a “good enough” solution to tide you over until browsers have good ECMAScript 3.1 compatibility.

Why Object.getPrototypeOf?

A common question at this point (and one that’s sure to come up often as new features start to trickle in from ECMAScript 3.1): Why is the method Object.getPrototypeOf("test") and not "test".getPrototypeOf() – or even just a property, like __proto__? While having a method, or property, on every object would certainly be more convenient to use it ends up being impractical for generalized use.

For example, take the following case into consideration:

var obj = { getPrototypeOf: "blah" };

Any attempt to call its getPrototypeOf method would end in failure, forcing the developer to always have to fall back to using the generalized Object.getPrototypeOf. Since most uses of getPrototypeOf would be required to work in the general case the fallback would always have to be used. Thus it’s not necessary to include it as an extra property of every object.

Additionally, it makes it far easier to backport to old implementations since you no longer have to extend the Object prototype (Object.prototype.getPrototypeOf = ...;) which would’ve been bad in any case.

@Resig: Yeah I read that, pity, since it’s code like the one above (and I do not specifically mean your code, its great, I mean that you actually need to write code like the one above to just achieve what you would with the super keyword) that scares developers away from JavaScript.

Object.getPrototype(this) should be returning Norris.prototype, which should have the above kick function, not the kick function from Person. Otherwise, Object.getPrototype(new Norris()) !== Norris.prototype.

Ah, I see it now. Object.getPrototype(this) returns Norris.prototype. Norris.prototype.kick calls the same function, but Object.getPrototype(this) returns Person.prototype the 2nd time, since it is being called on Norris.prototype, so it does eventually get to the right ‘kick’.

@John: Would modifying the return value of getPrototypeOf be local to the object? I would expect it to modify all objects that have the same prototype while assigning a new __proto__ property effectively enables assigning new behavior to an object in one step. I particularly need this behavior to be able to unapply traits from objects in my js meta system as demonstrated in the unapply method here: http://code.google.com/p/joose-js/source/browse/trunk/lib/Joose/Role.js

I haven’t found a way to do this in IE with its current JS implementation.

@Malte: You’re correct in assuming that the result of getPrototypeOf will point back to the original prototype object – not the one existing on this particular object (as is the case with __proto__). In that respect it isn’t as useful as __proto__.

Interesting, though i see problems with the Cross-Browser Implementation, constructor points to the same as constructor.prototype.constructor, at least for real js objects. ( e.g. with your instanceOf implementation you would end up in an endless loop in a browser without __proto__ support )

@John –
“In this example we traverse up the prototype chain, checking each constructor along the way.”

That’s not quite accurate. The code doesn’t check *each* constructor, it gets each prototype and compares it to the prototype property of the constructor parameter.

The usefulness of getPrototypeOf is that it is reliable, unlike the constructor property:
function F(){}
function G(){}
G.prototype = new F;
new G().constructor === F; // true, constructor property is dynamic.

There’s a little more going on in the Norris -> Person example. You’re recursively calling kick and changing the
thisArg to have static context. In effect, the end result is: Person.prototype.kick.call(Norris.prototype, "Roundhouse")

…but it looks as if Noah pointed that out.

I already wrote up my comments, so might as well post it.

Garrett

Comments are closed.
Comments are automatically turned off two weeks after the original post. If you have a question
concerning the content of this post, please feel free to contact me.