arguments.callee in Harmony

Charles Jolley charles at sproutit.com
Thu Sep 24 14:56:13 PDT 2009


Hi everyone,

First an introduction: I am the lead developer of SproutCore (http://www.sproutcore.com 
), an open source framework for building client-side applications in  
HTML5.  SproutCore is used in several large projects including Apple's  
MobileMe and iwork.com, OtherInbox, and some other large projects that  
are not yet public.

Point is, we write very large applications in JavaScript and HTML5.   
I've been following ES5/Harmony closely.  By and large I am very  
excited about the features to be added.  One critical feature (imo)  
that is missing, however, is "arguments.callee" - at least some way to  
identify the current function that is executing.

I spoke with Brenden Eich and Yehuda Katz about this on Friday and  
talked to Doug Crockford about it today and they suggested I email  
this list to make my case so here it is:

USE CASE

Currently SproutCore implements a class-like system on top of  
JavaScript.  That is, you can have "classes" with "subclasses" and you  
can instantiate both.  SproutCore is not strictly classical, and JS is  
not class-based of course, but I think this is a pattern that many  
developers commonly want to implement and use in JS.

The problem comes with implementing methods that "override" methods in  
superclasses.  Take the following example [extend() is the SproutCore  
function that creates a new "subclass"]:

ClassA = SC.Object.extend({

   foo: function() {
     // do something
   }

});

ClassB = ClassA.extend({

   // NOTE: overrides foo in classA!
   foo: function() {
     // call ClassA.foo();
     // do something else
   }

});

--

Now the question is, how can ClassB.foo() call ClassA.foo() in a  
generic fashion?

I could force developers to hard code this knowledge  (i.e. when  
implementing ClassB.foo() you have to explicitly call ClassA.foo.apply 
(this)) but this is prone to developer error and also makes the code  
not easily transportable from one method to another; violating the  
sort of "copy-and-paste" ethos that is part of JavaScript.

I've been told that I could name the functions.  e.g.:

ClassB = ClassA.extend({
   foo:  function foo() {
     // ..code
   }
});

Somehow that should solve my problem, though I can't really work out  
how.  But regardless, asking developers to name each method twice in  
the declaration is also error prone and fragile.

--

The way I solve this currently is to implement extend() so that when  
it copies an overloaded method, it sets a property ("base") on the  
Function to point to the Function it is overloading.  In the example  
above, for example, this means that ClassB.foo.base === ClassA.foo.

This way I can write a generic call to "super" like so:

ClassB = ClassA.extend({

   foo: function() {
     arguments.callee.base.apply(this, arguments); // calls super!
     // other code
   }

});

--

I realize this is not the most elegant looking code, but currently its  
the only way I can figure out to implement the "super" pattern in a  
generic way in JS.

SOLUTIONS?

With ES5, arguments.callee is gone.

One suggestion Brenden had was to perhaps include a "thisFunction" or  
some such property that returns the current function instance you are  
in.  This seems useful to me for a bunch of other meta-programming  
patterns as well but would certainly work here.

Another solution suggested by Douglas would be to provide a way for a  
function to get its current "name" AND for ECMAScript to follow a  
convention that anonymous functions when declared as part of an object  
literal take on the name they are assigned to by default.

Either of these would work for this pattern; there are probably other  
solutions as well.

I don't really care what ends up in the final implementation only that  
there is some way to generically implement the ultra-common class- 
based-with-method-overloading pattern in ECMAScript >= 5 without  
jumping through some crazy hoops.

--

So that's my best argument on this.  Any suggestions of alternative  
implementations that will work in ECMAScript 5?  If this is a  
limitation of the new language, what I can do to agitate for something  
to be added?

Thanks,
-Charles

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20090924/101bc73e/attachment-0001.html>


More information about the es-discuss mailing list