Inner functions and outer 'this' (Re: That hash symbol)

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Mar 28 10:35:59 PDT 2011


On Mar 27, 2011, at 11:13 AM, David Herman wrote:

> To be fair, your suggestion is more moderate than de Bruijn, although it's not clear whether you're proposing the ability to refer to shadowed bindings of *all* variables or just |this|. If it's the former, I'm *strongly* opposed. If it's the latter, well, I guess I'm still pretty opposed, just maybe less strongly. :)


Dave, I think that applying this solution to the this-scoping issue may be a really good idea

Claus, thanks from bringing a new (old) idea into the discussion.

I agree with Dave about all the fragility issues he mentioned for the general case.  Also, I just don't see the general problem (if it is even a "problem") as one that is important enough to try to "fix" in the language  since it is probably rare and  it can be avoided by careful naming.

However, the specific case of 'this' is a different matter.    'this' is implicitly rebound in every function scope and the JavaScript programmer has no direct control over the naming and shadowing.  The result is that they have to know and use the self renaming pattern.

This issue shows up enough in defining objects via object literal methods and in methods that call higher order functions that it is something that may well be worth addressing in the language.  Particularly as we discuss adding additional declarative forms to Harmony that included nested method definitions.  The outer 'this' problem is limited enough that we can avoid things like dynamic scoping complications in the solution.  Also it is limited enough that I don't believe that the solution imposes refactoring complications.  

Here is a sketch of a proposal:

^this is added as a new lexical token of the language. When spoken it is pronounced as "outer this" .  In the expression grammar ^this is a primary expression.

It is a syntax error for ^this to appear outside of a function body.  It may not occur at the top level of a program.  

When evaluated, the value of ^this is the this binding of the function that immediately lexically encloses the function body that contains the ^this.  It is a early syntax error if there is no such function.  For example:

//at the top level
var self = ^this;  //syntax error, at the top level
function foo() {
   ^this.bar();  //syntax error, no enclosing function
}

The two primary  use cases for ^this are exemplified by the following two examples:

MyObj.prototype.addClickHandingForElement(elem) {
   elem.addEventListener('click', function (e) {^this.handleClick(this,e)});
}

MyObj.prototype.wrap = function () {
   // create a wrapper object that limits access to the properties of one of my objects
   return {
        name: this.id,  //fix name of wrapper at creation (uses this of wrap call
        get foo () {return ^this.foo},  //outer this is this of wrap call
        set bar(val) {^this.bar = val}  //outer this is this of wrap call  
}
      
Note that only one level outer this access is supported, ^^this would be a syntax error.  In the rare cases where somebody really needs deeper access to shadowed this binding then they can fall back to the self pattern. 

I see minimal refactoring hazards here as the outer scope reference is limited to one level, is  explicitly marked at the usage site, and only applies to this.

Possible reservations: 
This use of ^ probably would preclude its use as a short form of the 'return' keyword (for those people who aren't in favor of adding implicit returns).
It looks odd to old Smalltalk programmers.

Overall, I really like ^this as a narrow solution to a specific real usage problem. I'm interested in reactions and unless somebody thinks of something that seriously torpedoes it I will probably write it up as a strawman. 

Allen


More information about the es-discuss mailing list