issue: function hoisting and parameter default value initialization

Brendan Eich brendan at mozilla.org
Mon Oct 8 16:55:19 PDT 2012


Andreas Rossberg wrote:
> On 6 October 2012 02:35, Allen Wirfs-Brock<allen at wirfs-brock.com>  wrote:
>> Bottom line,
>>    I suggest we implement proposal 3, rather than the temporary conclusions
>> that were discussed at the Sept. meeting.
>
> Of the options you suggest, I also think that #3 is preferable.

I do too.

> However, your examples have reconfirmed my suspicion that having
> defaults live within the scope of local declarations is the path to
> insanity. I suggest that we reconsider. There should be a clean,
> simple, and sane nesting of scopes here.
>
> Let me try again. How about the following desugaring?
>
>    function f(x1 = e1, ~~~, xN = eN) { body }
>
> means
>
>    function f(x1, ~~~, xN) {
>      if (x1 === undefined) x1 = e1;
>      ~~~
>      if (xN === undefined) xN = eN;
>      return (function(x1, ~~~, xN) { body })(x1, ~~~, xN);

Nit: need (function(x1, ~~~ xN) { body }).call(this, x1, ~~~ xN) and not 
a direct this-free call.

>    }
>
> That is:
>
>    * no local declaration is visible in any of the defaults
>    * defaults can see other parameters, but they are initialized left to right
>    * local declarations behave as always, no extra rules needed

This still is seems observable, because arguments.length will always be 
N, even when f is called with < N actual parameters.

The fix that uses apply:

function f(x1, ~~~, xN) {
     if (x1 === undefined) x1 = e1;
     ~~~
     if (xN === undefined) xN = eN;
     return (function(x1, ~~~ xN) { body }).apply(this, arguments);
}


seems to suffice (check me on this!).

> There is an additional advantage to this scheme: to understand the
> definition of a default a caller never needs to look at the
> implementation details of f's body -- which I think is a very useful
> property.

I agree.

>   In particular, if a default expression is itself a function,
> and closes over one of the other arguments, then you actually get what
> you'd expect even if f, way down in its body, messes with some of
> those arguments (e.g. abusing them as a loop variable):
>
>    function f(i, log = (s) =>  print("f(" + i + "): " + msg)) {
>      log("starting...");
>      while (i>  0) {
>        log("processing " + i);
>        // ... whatever
>        --i;
>      }
>      log("done...");
>    }
>
>    f(6);  // no surprises here

JS has such surprises already, of course, but appreciate trying to draw 
a line here.

/be


More information about the es-discuss mailing list