From: Garrett Smith on
Johannes Baagoe wrote:
> Stefan Weiss :
>> Johannes Baagoe :
>
[...]

> You are right, I can't. If I want to define 21! inline using neither
> named function expressions nor function declarations, the best I have
> come up with is
>
> ((function() {
> return fact = function(n) {return n > 0 ? n * fact(n - 1) : 1;};
> }())(21));
>
> which is hardly a model of legibility.
>

Or design.

Syntactially, it could do without the excess grouping operator and
certainly can do without creating a global identifier within a function.

However if the goal is to write a factorial function, it would be best
to focus on that; so changing the syntax would miss the point.

A factorial function should consider input > 170, i.e. throw a
RangeError, utilize a user-defined `BigNumber`, etc.

> So there may legitimate uses for named function expressions after all.
> The trouble is that their formal definition is so badly ambiguous
> that I immediately object on aesthetic if not on sound theoretical
> grounds, but I admit that if the implementations always get it right,
> it becomes little more than a matter of taste. (Of course, if MDC
> doesn't lie, some implementations *don't* get it right, which gives
> rather more weight to my theoretical pretexts.)
>

The formal grammar for FunctionExpression, with optional Identifier, can
be easily understood.

MDC published misinformation there, unfortunately. I do not know why you
cannot see that; I have explained it well enough twice now. If there is
any part of my explanation that was confusing, or that you thought was
wrong, please specify.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Johannes Baagoe on
Garrett Smith :

> Then what is wrong with an implementation treating a FunctionExpression
> as a Function Definition?

Nothing at all, a FunctionExpression *is* a Function Definition.

> And if the answer is nothing (which is the correct answer) then why
> insist Microsoft got that wrong?

Apparently, MDC got at least *its* wording wrong : what "Some
JavaScript engines, not including SpiderMonkey" *may* do wrong (I
can't figure out whether it is true) is not to "incorrectly treat
any function expression with a name as a function definition",
but to incorrectly treat any function expression with a name as a
function *declaration*.

MDC's bone of contention is this:

if (0) {
function zero() {
document.writeln("This is zero.");
}
}

According to MDC, we have a function *expression*, which means that
zero is undefined unless defined elsewhere. js bears that out.

At least V8 (Chrome) considers it a function *declaration*, i.e.,
zero is a function.

I am not sure myself - understanding the specs requires more than
I am willing to spend on the problem, after having given it a try
both in 3rd and 5th ed. If someone can explain it in plain words to
an ordinarily stupid programmer like me, I shall be very grateful.

In any case, someone is wrong. It may be Microsoft (that was Jorge's
assumption, I have no personal opinion on the subject, not being
a Microsoft costumer), in which case Chrome is just as wrong. It
may be Mozilla. If I understood the specs, I would know, but I don't.

But for exactly that reason, I think whoever is wrong has at least a
"lame excuse", lamer, to be sure, in the case of people who get paid
to get it right than in mine. Namely that the specs are horrible:

FunctionDeclaration :
function Identifier ( FormalParameterList opt ) { FunctionBody }
FunctionExpression :
function Identifier opt ( FormalParameterList opt ) { FunctionBody }

mean that when the FunctionExpression has its optionalIdentifier, there
is nothing in its syntax to differentiate it from a FunctionDeclaration.
That is a syntactic ambiguity of about the worst sort imaginable.

How is it resolved? Well... happy reading of the specs :)

On the other hand, if the "Identifier opt" part in the definition of
FunctionExpression were removed, there would be no ambiguity at all.

Which explains my perhaps excessive dislike of named function expressions.

--
Johannes
From: Johannes Baagoe on
Jorge :

[named function expressions]

> 1.- They're not used much due to the named function expressions BUG
> in Microsoft's Internet Explorers (in ALL of them).

That may the case for many people, but it has nothing whatsoever to
do with *my* dislike of named function expressions. I hate them
because their syntax sucks. Bugs in Microsoft products are of no
concern to me, since I don't use them.

> 2.- The function's name is defined inside the function, where it's
> safer (and faster too) than in the enclosing scope.

Where that is a concern, I use a function declaration.

> 3.- (function functionName () {}).name is === "functionName".
> So you can get it from the outside, if you ever need to.

I don't, since I don't use named function expressions. If I want to
use a function more than once, either I declare it, or I assign its
expression to a variable.

> Plus a 4th point of my own:

> 4.- [...] Microsoft has been careful not to fix ever, have had the
> (intended) effect [...] Microsoft's own interests, [...] Make no
> mistakes: it's not by coincidence.

I couldn't care less about Microsoft. On the other hand, I don't
speculate on nefarious motives and intents, either.

--
Johannes
From: Garrett Smith on
Johannes Baagoe wrote:
> Garrett Smith :
>
>> Then what is wrong with an implementation treating a FunctionExpression
>> as a Function Definition?
>
> Nothing at all, a FunctionExpression *is* a Function Definition.
>
>> And if the answer is nothing (which is the correct answer) then why
>> insist Microsoft got that wrong?
>
> Apparently, MDC got at least *its* wording wrong : what "Some
> JavaScript engines, not including SpiderMonkey" *may* do wrong (I
> can't figure out whether it is true) is not to "incorrectly treat
> any function expression with a name as a function definition",
> but to incorrectly treat any function expression with a name as a
> function *declaration*.
>
> MDC's bone of contention is this:
>
> if (0) {
> function zero() {
> document.writeln("This is zero.");
> }
> }
>
> According to MDC, we have a function *expression*, which means that
> zero is undefined unless defined elsewhere. js bears that out.
>

Actually that is a FunctionStatement, an allowed syntax extension.

The documentation there uses "function statement" in two ways:
1) Parenthetically, as an alternative for FunctionDeclaration (wrong)
2) To mean the syntax extension "FunctionDeclaration" (right)

<https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions#section_15>


> At least V8 (Chrome) considers it a function *declaration*, i.e.,
> zero is a function.
>

The function declaration (function statement)
Edit section

> I am not sure myself - understanding the specs requires more than
> I am willing to spend on the problem, after having given it a try
> both in 3rd and 5th ed. If someone can explain it in plain words to
> an ordinarily stupid programmer like me, I shall be very grateful.
>
> In any case, someone is wrong. It may be Microsoft (that was Jorge's
> assumption, I have no personal opinion on the subject, not being
> a Microsoft costumer), in which case Chrome is just as wrong. It
> may be Mozilla. If I understood the specs, I would know, but I don't.
>

Microsoft has a well known bug with named function expressions. There
are many posts in the archives, but Juriy's article explains it in one
place (that is also linked from the FAQ).

> But for exactly that reason, I think whoever is wrong has at least a
> "lame excuse", lamer, to be sure, in the case of people who get paid
> to get it right than in mine. Namely that the specs are horrible:
>
> FunctionDeclaration :
> function Identifier ( FormalParameterList opt ) { FunctionBody }
> FunctionExpression :
> function Identifier opt ( FormalParameterList opt ) { FunctionBody }
>
> mean that when the FunctionExpression has its optionalIdentifier, there
> is nothing in its syntax to differentiate it from a FunctionDeclaration.
> That is a syntactic ambiguity of about the worst sort imaginable.
>

Not at all. The ECMAScript specification has no provision for
FunctionDeclaration to appear where a Statement may appear.

However, an ExpressionStatement may appear where a Statement is allowed.
A FunctionExpression is an ExpressionStatement. Therefore, a
FunctionExpression may appear where a Statement is allowed.

> How is it resolved? Well... happy reading of the specs :)
>

| Statement
| Block
| VariableStatement
| EmptyStatement
| ExpressionStatement
| IfStatement
| IterationStatement
| ContinueStatement
| BreakStatement
| ReturnStatement
| WithStatement
| LabelledStatement
| SwitchStatement
| ThrowStatement
| TryStatement

FunctionDeclaration is not on that list.

ExpressionStatement is.

ExpressionStatement
ExpressionStatement
[lookahead {{, function}] Expression

An ExpressionStatement can't start with "{" because that would create
ambiguity to determine if it is a block or an object literal and it
can't start with "function" because that could it ambiguous with a
FunctionDeclaration (s 12.4).

A MemberExpression is a Left-Hand-Side Expression.

MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . Identifier
new MemberExpression Arguments

A FunctionExpression is an MemberExpression.

A FunctionDeclaration is not an Expression; it is a SourceElement.

Spidermonkey adds FunctionStatement. JScript adds FunctionDeclaration,
however, JScript also has JScriptFunction.

In JScript, upon entering an execution context, each
FunctionExpression's identifier and each FunctionDeclaration's
identifier, and all identifiers in a JScript FunctionBindingList of a
JScriptFunction are added as properties of the containing Variable object.

| For each FunctionDeclaration or FunctionExpression in the code, in
| source text order, do one of the following depending upon the form of
| the FunctionDeclaration or FunctionExpression:
| * If the production is of the form
| FunctionDeclaration : function ( FormalParameterListopt )
| { FunctionBody }
| or
| FunctionExpression : function ( FormalParameterListopt )
| { FunctionBody }
|
| do nothing.
| * If the production is of the form
| FunctionDeclaration : function Identifier ( FormalParameterListopt )
| { FunctionBody }
| or FunctionExpression : function Identifier (
FormalParameterListopt ) { FunctionBody } create a property of the
variable object whose name
is the Identifier in the FunctionDeclaration or FunctionExpression,
whose value is the result
returned by creating a Function object as described in 13, and whose
attributes are determined
by the type of code. If the variable object already has a property with
this name, replace its value
and attributes. Semantically, this step must follow the creation of
FormalParameterList
properties.
 If the production is of the form FunctionDeclaration : JScriptFunction
or FunctionExpression :
JScriptFunction perform the following steps:
1. Let func be the result returned by creating a Function object as
described in 13.
2. Process the FunctionBindingList element of the JScriptFunction as
described in 13 and using func
and the attributes for the current type of code as processing arguments.
[...]
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Stefan Weiss on
On 21/04/10 02:06, VK wrote:
> On Apr 21, 2:46 am, VK <schools_r...(a)yahoo.com> wrote:
>> This IE's behavior is won't-fix anyway, so not a bug but a peculiarity
>> (aka a feature), so interesting for a theoretical discussion only.

That they've decided not to fix it doesn't make it any less a bug. You
can call it a feature, if you want, but don't get upset when others
don't agree with you.

>> From this theoretical point of view I'd like to grasp - and be
>> merciful on my weak mind - why
>> var bar = (function foo(){/*whatever*/}())
>> window.alert(typeof foo); // function
>> pisses some Mozilla people off for year while
>> var a = (b = 1);
>> window.alert(a);
>> window.alert(b); // 1
>> keeps them relaxed?

Because one works as specified, and the other doesn't.

> Or for that matter:
>
> <script type="text/javascript">
> var a = ( (b = 1) + 1 );
> window.alert(a); // 2
> window.alert(b); // 1
>
> function f() {
> var c = ( (d = 1) + 1 );
> }
>
> f();
>
> window.alert(typeof c); // undefined
> window.alert(typeof d); // number
> </script>
>
> and it is OK but FunctionExpression is a matter of some silly rwar for
> years? I mean since when (expression parenthesis) became contextually
> dependent visibility scope regulators in JavaScript? Did I miss some
> important events?

You may have missed what happens when you assign to an undeclared
identifier: it becomes a property of the global object. Are you asking
why 'c' was kept local and 'd' wasn't, or are you asking why people
think that's a good thing?


--
stefan