Newly revised Section 10 for ES3.1.
Richard Cornford
Richard at litotes.demon.co.uk
Sat Jul 12 15:14:58 PDT 2008
Brendan Eich wrote:
> On Jul 10, 2008, at 4:02 PM, Richard Cornford wrote:
>> Something like:-
>>
>> fucntion getSomething(arg){
>> if(caseOneTest){
>> getSomething = function(x){
>> //actions appropriate for case one
>> };
>> }else if(caseTwoTest){
>> getSomething = function(x){
>> //actions appropriate for case two
>> };
>> }else{
>> getSomething = function(x){
>> //actions appropriate for other cases
>> };
>> }
>> return getSomething(arg);
>> }
>>
>> It is the ability to do this sort of thing that helps make
>> javascript so well suited to browser scripting.
>
> Oliver Steele blogged about this kind of memoization a couple
> of years ago:
>
> http://osteele.com/archives/2006/04/javascript-memoization
>
> although his examples did not show top-level function being
> replaced.
I was shown examples of doing this sort of thing back in 2002
shortly after I first started using javascript, so even if it
has never become that common it certainly is not a new idea.
> But it's a good point: strict mode wants to break useful (and
> used) patterns that change the value of a property created by
> a defining form.
I spend yesterday's commute to work thinking about this and
came to the conclusion that I am completely wrong. If "Illegal
to assign to a top-level function name" is interpreted as
meaning (or re-worded to effetely say) that it is illegal to
assign to a top-level name (activation/environment object
property, or however that is best expressed) that was
created_as_the_result_of_a_function_declaration (as opposed
to a possible interpretation where it is illegal to assign
to a top-level name that happens to refer to a function
object) then there isn't really a problem.
There is no problem because if I want a self-reconfiguring
function I can create one with a function expression. I.E.:-
var getSomething = function(arg){
if(caseOneTest){
getSomething = function(x){
//actions appropriate for case one
};
}else if(caseTwoTest){
getSomething = function(x){
//actions appropriate for case two
};
}else{
getSomething = function(x){
//actions appropriate for other cases
};
}
return getSomething(arg);
};
- and have the same facility for a negligible difference in
effort. The minor change in execution, where a function
declaration creates its function during variable instantiation
and the above would create it at the execution of the assignment,
isn't too problematic. It just means that the code that creates
the function has to run before any code that attempts to use it
(which is already true of much more common constructs such as
the (so called) 'Crockford Module Pattern').
As this is "the cautious subset"/'strict' mode (or however it is
to be known) we are talking about code that is yet to be written;
so long as the facility remains the details of how it is achieved
are not too important (at least so long as the useful existing
possibilities don't become significantly more difficult to
achieve).
> From Allen's list:
>
>· Illegal for a function to have duplicately named formal
> parameters
>· Illegal for a function to contain a top level function
> declaration with a function name that is the same as a formal
> parameter.
>· Illegal to have multiple top level function declarations
> for the same function name
>· Illegal to have a function declaration with the same name
> as var declaration.
>· Illegal for a function to contain a var declaration with
> the same name as a formal parameter.
I liked all of these from the outset. If I do any of these in the
code I write then I have made a mistake, and being told as much
ASP means that I can fix that mistake sooner rather than later.
>· Illegal to assign to a top-level function name.
And in retrospect that one is OK too. If I don't what a top-level
function replaced I can use a function declaration, and if I do I
can assign a function expression to a variable; a little externally
imposed formal discipline (and no harm in that).
> I could see banning duplicate formal parameter names (I still
> have no memory of why Shon from Microsoft wanted these
> standardized in ES1 -- possibly just because JScript already
> allowed them).
I could not think of anything useful that could be done with
multiple like-named formal parameters. The nearest I could get is
if you wanted an object with a read-only - length - property of
varying magnitude you could do something like:-
function makeFixedLengthObject(sizeOfLength){
function F(){}
var c, ar = [];
for(c = 0;c < sizeOfLength;++c){
ar[ar.length] = 'a';
}
// The length of the array determines the value of the
// length property of the constructed function object.
F.prototype = new Function(ar.toString(), 'return');
// Hide the function methods so they will not be inherited
// by the returned object.
F.prototype.apply = undefined;
F.prototype.call = undefined;
F.prototype.toString = Object.prototype.toString;
return new F();
/* The function object used as a prototype has a read only -
length - property and the read only attribute is
(effectively) inherited through the prototype chain
so the returned object here has a read only - length
- property as well.
*/
}
But I cannot envision a use for such an object, and it doesn't
actually need like-named formal parameters because it would not
be too hard to program the parameters to be a, aa, aaa, aaaa and
so on.
> Shadowing a formal parameter with a nested function name also
> seems likely to be a mistake.
>
> Multiple top-level function definitions having the same name?
> That must be allowed if the definitions are in separate scripts.
I have seen an HTML template system where the top of the template
defined a dummy function and the BODY onload attribute called that
function unconditionally, with the idea that specific pages would
insert or import a script that would declare a like-named
replacement for the dummy function whenever they needed something
executed onload.
> In the same script, it could be a mistake, or a fast patch of
> some kind. Without #if 0 or nested comments (ES1-3 do not
> require them, I don't know of any implementations that do
> them either) it's hard to hide bulk code. Anyway, this seems
> less likely to be fruitful as a "good taste" strict-mode
> check, more somewhat likely to bite back.
The list does not include an "illegal to have multiple like-named
variable declarations", so maybe something else that could be
worked around by insisting that if there were to be more than one
they each take the form of assigning a function expression to a
declared variable? (as the "strict" mode implies an opt-in and
new code)
> Within the same program, function vs. var name conflict is
> probably a mistake to catch. I don't see it in web JS, but
> I'm not sure how uncommon it is. Anyone have insights?
My judgment would be very uncommon.
> Function containing a var x and taking formal parameter x?
> That's allowed and might be tolerated if the var has no
> initialiser, but if the var has an initialiser then it
> is very likely to be a mistake.
I have seen a lot of event handlers take the form:-
el.onsomething = function(ev){
if(!ev){
var ev = window.event;
}
//code that used ev (the event object);
};
- with increasing frequency over the last couple of years.
Presumably following an example from a book or somewhere. It is
something between a misconception and a mistake (as in ES3 it
is harmless), and I would have no problem with a 'strict' mode
complaining about it.
> Even when hacking and debugging it's rare to nullify
> an actual argument by declaring a var and assigning
> to it in the var declaration -- one would just assign
> without adding a var at the front.
You and I would, but unfortunately ...
More information about the Es4-discuss
mailing list