Just a side note: The code below would create three Function objects per Point instance. Some may argue that the days of having little memory are long gone, but we still have small devices plus a garbage collector that may need to iterate through live objects, including three Function objects per Point. Long live prototype objects.
Michael -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Mark S. Miller Sent: Tuesday, August 19, 2008 5:41 PM To: Peter Michaux Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED] es4-discuss; TC39; [EMAIL PROTECTED] x-discuss Subject: Look Ma, no "this" (was: ECMAScript Harmony) On Wed, Aug 13, 2008 at 7:15 PM, Peter Michaux <[EMAIL PROTECTED]> wrote: > On Wed, Aug 13, 2008 at 2:26 PM, Brendan Eich <[EMAIL PROTECTED]> wrote: > > [snip] > >> We talked about desugaring classes in some detail in Oslo. During >> these exchanges, we discussed several separable issues, including >> classes, inheritance, like patterns, and type annotations. I'll avoid >> writing more here, > > Is there more to read elsewhere? I'd like to know concretely what > "desugaring classes" means. The main difference from the old "Classes as Sugar" proposal is to desugar to the objects-as-closure style pioneered by Crock rather than ES3-classical style of prototypical inheritance + this-binding. Point as a final root class: function Point(x, y) { const self = Object.create(Point.prototype, { toString: {value: Object.freeze(function() ('<' + self.getX() + ',' + self.getY() + '>'))}, enumerable: true}, getX: {value: Object.freeze(function() x), enumerable: true}, getY: {value: Object.freeze(function() y), enumerable: true} }, true); return self; } (Assuming that absent attributes default to false, which I don't think is currently the case in the ES3.1 draft.) If we stick with zero inheritance, which seemed attractive at Oslo, we can skip the part about inheritance below. Otherwise, read on. <inheritance> Point as a non-final non-abstract root/mixin class where toString is a final method: function PointMixin(self, x, y) { Object.defineProperties(self, { toString: {value: Object.freeze(function() ('<' + self.getX() + ',' + self.getY() + '>'))}, enumerable: true}, getX: {value: Object.freeze(function() x), enumerable: true, flexible: true}, getY: {value: Object.freeze(function() y), enumerable: true, flexible: true} }); } function Point(x, y) { const self = Object.create(Point.prototype); // only for instanceof PointMixin(self, x, y); return Object.freeze(self); } Object.freeze(PointMixin); Object.freeze(Point.prototype); Object.freeze(Point); WobblyPoint as a non-abstract non-final subclass: function WobblyPointMixin(self, wobble) { const super = Object.snapshot(self); // a snapshot is a frozen copy Object.defineProperties(self, { getX: {value: function() (super.getX() + Math.random()*wobble), enumerable: true, flexible: true} }); } function WobblyPoint(x, y, wobble) { const self = Object.create(WobblyPoint.prototype); // only for instanceof PointMixin(self, x, y); WobblyPointMixin(self, wobble); return Object.freeze(self); } Object.freeze(WobblyPointMixin); WobblyPoint.prototype = Object.create(Point.prototype, { constructor: {value: WobblyPoint} }, true); Object.freeze(WobblyPoint); This gets self-overriding a super-binding correct under single inheritance and even under linearized multiple inheritance. </inheritance> Further, methods auto-bind on extraction, as they did in ES4: const pt = new WobblyPoint(3, 4, 0.1); const gx = pt.getX; gx is a no argument function bound to pt. For ES3-style classical code, you'd instead have to say "pt.getX.bind(pt)". Notice that the above code works well *because* it never says "this". JavaScript's "this" is an incredibly tricky construct. However, the above technique is impractical today because of the extra allocation cost -- one closure per method per instance. But as Dan Ingalls says "you can cheat if you don't get caught." The above desugaring shows how to define the *semantics* of the class construct. The actual behavior of the class construct must not be observably different from some such desugaring. But in a class-aware implementation, it should of course perform better than you'd expect from this desugaring. In the Caja project, we are exploring whether this optimization can even be provided as a source-to-source translation: <http://google-caja.googlecode.com/svn/trunk/doc/html/cajitaOptimization /index.html>. It's not yet clear that the idea is practically implementable by this technique <http://groups.google.com/group/google-caja-discuss/browse_thread/thread /df6c8ea9a1ca1aa3>. But none of these problems should impede a more directly implemented optimization. -- Cheers, --MarkM _______________________________________________ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss