issue: function hoisting and parameter default value initialization

Aron Homberg info at aron-homberg.de
Sat Oct 6 03:37:29 PDT 2012


Idea:

Additionally disallow redeclaration (I mean redeclaration not reassignment; eg. by parameter name in parameter list or function identified by a name already in in use) with different type in same function scope when code is executed in ES6 strict mode. (New strict mode rule.) 

This should not break existing code (okay, it could break crazy es5 code which already runs in strict mode and makes use of redeclaring with different type - but I guess this would just point out existing bugs) and helps developers to prevent writing crazy, buggy code even when they aren't aware of this. 

Redeclaring variables with different type in same function scope often leads to hard to find bugs in practice. 

- Aron


Am 06.10.2012 um 02:35 schrieb Allen Wirfs-Brock <allen at wirfs-brock.com>:

> The Sept 20 TC39 meeting notes says the following was (almost) agreed regarding function parameter scoping,  pending some further investigation.
> 
>> Temporarily, this happened:
> 
>> Conclusion/Resolution
>> - `var` bindings and are in scope within the function
>> - cannot use `let` to shadow a parameter
>> - defaults can refer to any top level binding
> 
>> **Conclusion/Resolution**
>> Revisit when data is gathered, re: perf or unexpected behaviours
> 
> 
> We also agreed, that repeat use of an identifier as a parameter, for example:
> 
> function f(x,x,x,x) {}
> 
> is only allowed for legacy compatibility and that it will be an early error if repeated parameter names are used in a parameter list that contains any of the new ES6 parameter list syntactic affordances.  (Call this Agreement 0)For example, these would all be errors:
> 
> function f(x,x,x,x, ...x) {}
> function f(x,x=1)  {}
> function f( {x,x} ){ };
> 
> 
> An implication of the "defaults can rely on any top level binding" point is that parameter default value initializers can refer to inner functions defined using function top-level function declarations.  For example:
> 
> function f(p=computeDefaultValue()) {
>    function computeDefaultValue() {return Math.random()}
>    return p;
> }
> 
> The notes don't literally say this, but it was one of the intentions of that item that we discussed at the meeting.
> 
> This implies that inner function declaration initialization is hoisted ahead of formal parameter initialization.
> 
> This however exposes some strange interactions between ES<=5.1 rules regarding duplicate  parameter names that are the same as declared inner function.
> 
> ES5.1 requires that 
> 
> (function(p) {
>    return typeof p;
>    function p() {};
> })(1)
> 
> returns "function" rather than "number". 
> 
> To maintain compatibility, this means that if function initialization is hoisted before parameter initialization, that in cases like the above either
>    1) initialization of parameters that have the same name as a function declaration are skipped
>    2) declared functions that share names with formal parameters must be reinitialized to their original function value after parameter initialization
> 
> The choice of one of the above specification alternatives really doesn't make any observable difference,  as long as default value initializer aren't used.
> 
> However, alternative 1 introduces a specification (and perhaps implementation) complication.  Consider:
> 
> (function ({a:{b: {p}}}) {
>       function p() {};
>       return typeof p;
> }) ({a: {b: {p: 1}}});
> 
> The spec. complication is that deep within the destructuring algorithm we need to be able to skip any binding name that is the same as a declared function name.  
> 
> Also, it seems highly unlikely that anyone would actually want to give an inner function the same name as such a interior destructured parameter name.  It almost surely is a bug.  There are no backwards compatibility requires on such destructured parameter names, so:
> 
> Proposal #1:  Local bindings introduced via formal parameter destructing are treated as let bindings rather than var binding.  They cannot be the same as top inner function or var declared name.  There similarly are no compatibility issue with the name of the rest parameter, so it also should be treated as a let binding.
> 
> When default value initializers, the difference between approach 1 and 2 above becomes observable.  Consider,
> 
> function (p=[ ], q=p.length) {
>       function p(a,b,c) {};
>       return q;
> }) ();
> 
> If approach 1 above is used, the function call will return 3 -- the number of parameters of the inner function p.  If approach 2 is used, the function will return 0 -- the length of the empty array that provided the default value of the p parameter.
> 
> Another odd situation where the approaches would differ is:
> 
> function (a=p, p=1, c=p) {
>       function p() {};
>       return a===c;
> }) ();
> 
> If approach 1 is used, the function will return true.  If approach 2 is used the function will return false.
> 
> These are crazy things for anybody to code and it seems a waste to try to specify rationale runtime behavior for such irrational code.  Instead I suggest:
> 
> Proposal #2:  It is an early error if both any formal parameter is the same name as an top level inner function declaration and the formal parameter lists includes a destructuring, default value initializer, or a rest parameter.
> 
> Essential the net of Agreement 0 plus Proposals 1 & 2 would be that only ES<=5.1 style simple formal parameter lists may have repeated parameter names or parameter names that are the same as top level inner function declarations.
> 
> This could be even more cleanly expressed as:
> Proposal #3:
>        a) ES<=5.1 style formal parameters lists introduce var bindings and follow ES5.1 initialization rules. This permits top level inner functinon and var declarations that use the same name as a parameter.
>        b) parameter lists containing any new ES6 syntax introduce let bindings for the parameters.  This prohibits multiple declaration of a formal parameter name and inner var/function redeclaration of a parameter name.
> 
> Bottom line, 
>   I suggest we implement proposal 3, rather than the temporary conclusions that were discussed at the Sept. meeting.
> 
> Allen
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121006/4f8066c0/attachment-0001.html>


More information about the es-discuss mailing list