Monday, July 04, 2005

For the love of all that's good and holy

This JavaScript stuff is just getting silly. Every object has an internal prototype link, which is a reference to its prototype that, according to the spec, is not accessible to the user program. (The object's prototype is initially available as obj.constructor.prototype, but changing these fields doesn't affect the real prototype link.) There's a very good reason for hiding this link: the dynamic dispatch semantics searches the prototype chain automatically on field dereference (including method calls), and it would be a shame if cycles showed up in the prototype graph. I'm gonna make a rash generalization and guess that the legions of novice scripters would have no clue what was going on if simply dereferencing foo.bar caused their entire web browser to freeze.

But many implementations do expose the internal prototype link, via a non-standard __proto__ property! And what do they do about cycles? My guess was that they'd check for cycles during the dereferencing operation, but it appears they disallow it on mutation of the __proto__ field:
Rhino 1.6 release 1 2004 11 30
js> function Thing(v) { this.value = v; }
js> Thing.prototype = { common : 'blue' };
[object Object]
js> var thing1 = new Thing(1);
js> var thing2 = new Thing(2);
js> thing1.value
1
js> thing2.value
2
js> thing1.common
blue
js> thing2.common
blue
js> thing1.__proto__ == Thing.prototype
true
js> thing2.__proto__ == Thing.prototype
true
js> thing1.__proto__ = thing2;
[object Object]
js> thing2.__proto__ = thing1;
js: "<stdin>", line 12: Cyclic __proto__ value not allowed.
Good gravy, does everything have to be mutable?

No comments: