Closing parenthesis in function's definition followed by its call

178 views
Skip to first unread message

Johannes Baagoe

unread,
Apr 19, 2010, 9:55:31 PM4/19/10
to
Should it be

(function foo() { /*...*/ })();

or

(function foo() { /*...*/ }());

(note the place of the closing parenthesis) ?

Both are AFAICT syntactically correct and indeed equivalent, but
I would tend to prefer the latter: since we are warning the future
reader "Beware! This function is not only defined / declared but also
called right away!", why not make it quite clear where the scope of
that warning ends?

Same question for

var foo = (function() { /*...*/ })();

vs.

var foo = (function() { /*...*/ }());

etc.

It doesn't matter much when `foo` is called with an empty list
of arguments, but I believe it would make cases where its arguments
are complex much clearer - any editor that matches opening and closing
parentheses would immediately show the various parts of the construct.

Are there better arguments in favour of the former ?

--
Johannes

nick

unread,
Apr 20, 2010, 1:05:47 AM4/20/10
to
On Apr 19, 9:55 pm, Johannes Baagoe <baa...@baagoe.com> wrote:

> Same question for
>
>   var foo = (function() { /*...*/ })();
>
> vs.
>
>   var foo = (function() { /*...*/ }());

Those shouldn't need the extra parentheses...

var foo = function() { /*...*/ }();

...should be valid.

But nobody ever does that, which makes me think some old(ish) browsers
might be more picky, especially after reading this:

https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions
#Function_constructor_vs._function_declaration_vs._function_expression

"Some JavaScript engines, not including SpiderMonkey, incorrectly
treat any function expression with a name as a function definition"

-- Nick

Garrett Smith

unread,
Apr 20, 2010, 2:20:09 AM4/20/10
to
nick wrote:
> On Apr 19, 9:55 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
>
>> Same question for
>>
>> var foo = (function() { /*...*/ })();
>>
>> vs.
>>
>> var foo = (function() { /*...*/ }());
>
> Those shouldn't need the extra parentheses...
>
> var foo = function() { /*...*/ }();
>
> ...should be valid.
>
> But nobody ever does that, which makes me think some old(ish) browsers
> might be more picky, especially after reading this:
>

The Grouping operator merely provides is a hint at an idiom. Some omit it.

> https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions
> #Function_constructor_vs._function_declaration_vs._function_expression
>
> "Some JavaScript engines, not including SpiderMonkey, incorrectly
> treat any function expression with a name as a function definition"
>

That in and of itself is not a true statement. Moreover, it is
unsupported by the example that follows.

| Note: Some JavaScript engines, not including SpiderMonkey, incorrectly
| treat any function expression with a name as a function definition.
| This would lead to zero being defined, even with the always-false if
| condition. A safer way to define functions conditionally is to define
| the function anonymously and assign it to a variable:
|
| if (0) {
| var zero = function() {
| document.writeln("This is zero.");
| }
| }

The paragraph makes a statement about a function expression with a name
being treated as a function definition. That would be a true statement
if it had been rewritten as:

| Some JavaScript engines, not including SpiderMonkey, incorrectly

| parse any function expression with an identifier as a function
| declaration.

However, even at that, it is still unsupported by the example.

The FunctionExpression in the example does not have an identifier. It is
an anonymous function expression.

The value of `zero` can be expected to be undefined following the block
after the `if` statement. For example:

if (0) {
var zero = function() {
document.writeln("This is zero.");
}
}
alert(typeof zero);

- can be expected to elert "undefined".

So I'm afraid MDC is a bad source of information here. Unfortunately,
the Edit feature is non-functional in Firefox with or without javascript
enabled.

I am now getting:

| Service Unavailable
|
| The service is temporarily unavailable. Please try again later.

Hopefully they can fix the errors on MDC. That is pitiful.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Thomas 'PointedEars' Lahn

unread,
Apr 20, 2010, 8:53:04 AM4/20/10
to
Johannes Baagoe wrote:

> Should it be
>
> (function foo() { /*...*/ })();
>
> or
>
> (function foo() { /*...*/ }());
>
> (note the place of the closing parenthesis) ?
>
> Both are AFAICT syntactically correct and indeed equivalent, but
> I would tend to prefer the latter: since we are warning the future
> reader "Beware! This function is not only defined / declared but also
> called right away!", why not make it quite clear where the scope of
> that warning ends?

Incidentally, that is what Douglas Crockford recommends and the way his
argument goes, too, as you can see starting at about 00:29:27 h of "Act III:
Function the Ultimate" (when he starts talking about closures).¹ Contrary
to other of his opinions, I find the reasoning sound in this case, and have
rewritten function expression calls on occasion. I have tested the result
with various browsers and have observed no negative effects so far.

¹ <http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-3>

> Same question for
>
> var foo = (function() { /*...*/ })();
>
> vs.
>
> var foo = (function() { /*...*/ }());

Currently I am using such assignments more often than one of the statements
above, although to real properties (which become methods), seldom to
variables.



> etc.
>
> It doesn't matter much when `foo` is called with an empty list
> of arguments, but I believe it would make cases where its arguments
> are complex much clearer - any editor that matches opening and closing
> parentheses would immediately show the various parts of the construct.

Full ACK.

> Are there better arguments in favour of the former ?

I don't think so.


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Jorge

unread,
Apr 20, 2010, 9:11:39 AM4/20/10
to

I prefer the former, for as soon as I see a () my "attention: function
call" flag gets set, and I expect the function itself to stand by the
left hand side of the (), often neatly enclosed in its own parens. A
trailing ()) is not so neat and tidy. It's asymmetric and awful. This
is one of the rare cases in which Crockford's arguments have not
convinced me.
--
Jorge.

Johannes Baagoe

unread,
Apr 20, 2010, 10:59:00 AM4/20/10
to
Thomas 'PointedEars' Lahn :
> Johannes Baagoe :

>> var foo = (function() { /*...*/ })();
>>
>> vs.
>>
>> var foo = (function() { /*...*/ }());

> Currently I am using such assignments more often than one of the
> statements above, although to real properties (which become methods),
> seldom to variables.

<rant>

If I were to teach elementary programming these days (perhaps
fortunately for the students, I don't any longer), I would 1. use
javascript - or rather, ECMASCript in whatever version seems the most
reasonable, probably still 3rd - as "first" language, and 2. only
introduce function *declarations* at the very end of the course, as a
kind of afterthought - "You can also do it that way, and it may even
help older programmers who don't know better", or something like that.

This exposes the student from the very start to the idea that functions
are very, very important animals, quite as important as numbers and
strings, and that they can be assigned, stored in objets (in which
case we call them "methods" rather than "properties", but that hasn't
necessarily to be a big deal), passed as arguments to other functions
or even to themselves, etc.

Which is a most important notion if the student is ever to do
functional programming, lambda calculus, about any kind of maths, and
even philosophy or linguistics, where a functional view of language -
words and sentences as procedures, that is, parametrised behaviour
triggered by events - is a useful contrast to the more traditional
view of language as a representation of the world.

</rant>

--
Johannes

Johannes Baagoe

unread,
Apr 20, 2010, 1:04:51 PM4/20/10
to
nick :
> Johannes Baagoe :

>>   var foo = (function() { /*...*/ })();
>>
>> vs.
>>
>>   var foo = (function() { /*...*/ }());

> Those shouldn't need the extra parentheses...
>
> var foo = function() { /*...*/ }();
>
> ...should be valid.
>
> But nobody ever does that, which makes me think some old(ish) browsers
> might be more picky, especially after reading this:
>
> https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions
> #Function_constructor_vs._function_declaration_vs._function_expression
>
> "Some JavaScript engines, not including SpiderMonkey, incorrectly treat
> any function expression with a name as a function definition"

Quite, but even assuming correct implementations, I would still add the
parentheses (second version), as a help to myself, to programmers who
are new to javascript, and even to old javascript hands who recognise
the idiom. When one sees "(function", it means "this function is
going to be called right away - its body ends at the closing brace
that matches the first opening brace, and the entire construct ends
at the closing parenthesis that matches this one".

It is especially important if the result is not a Function, like

var two = (function() {return 2;}());

Taking all that trouble be pointless in this case, but since
javascript's scope of variables are functions, not blocks, and since
the usual way to provide other languages' notion of static variables
is closures, it is very often a useful idiom - one that must be
taught to anybody who starts on javascript, especially when coming
from other languages with a C-style syntax.

--
Johannes

Jorge

unread,
Apr 20, 2010, 1:21:03 PM4/20/10
to
On Apr 20, 7:05 am, nick <nick...@fastmail.fm> wrote:
>
> "Some JavaScript engines, not including SpiderMonkey, incorrectly
> treat any function expression with a name as a function definition"

LOL. And these engines are made by Microsoft and are called JScript
and are the ones used in each and every Internet Explorer, up to and
including the current, latest one.

And they manage miraculously to not only screw up the function
expression, but the function declaration too. Wonders of software
engineering.
--
Jorge.

Johannes Baagoe

unread,
Apr 20, 2010, 1:31:10 PM4/20/10
to
Jorge :
> nick :

>> "Some JavaScript engines, not including SpiderMonkey, incorrectly treat
>> any function expression with a name as a function definition"

> LOL. And these engines are made by Microsoft and are called JScript and
> are the ones used in each and every Internet Explorer, up to and
> including the current, latest one.
>
> And they manage miraculously to not only screw up the function
> expression, but the function declaration too. Wonders of software
> engineering.

In a sort of lame defence (why on earth am I trying to excuse Microsoft?),
it may be argued that function expressions with a name are a Really Bad
Idea from the beginning, and that anyone who uses them deserves... well,
some terrible fate.

--
Johannes

Jorge

unread,
Apr 20, 2010, 1:37:42 PM4/20/10
to
On Apr 20, 7:31 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
>
> In a sort of lame defence (why on earth am I trying to excuse Microsoft?),
> it may be argued that function expressions with a name are a Really Bad
> Idea from the beginning, and that anyone who uses them deserves... well,
> some terrible fate.

Huh ?
How so ?
--
Jorge.

Garrett Smith

unread,
Apr 20, 2010, 4:05:31 PM4/20/10
to
Johannes Baagoe wrote:
> Garrett Smith :
>> Johannes Baagoe :

>>>> nick :
>
>>>>> "Some JavaScript engines, not including SpiderMonkey, incorrectly
>>>>> treat any function expression with a name as a function definition"
>
>>> In a sort of lame defence (why on earth am I trying to excuse
>>> Microsoft?),
>
>> If you're asking me to guess, I would say that you have probably
>> mistaken "function definition" with "function declaration".
>
> I hope not. I talk about a function expression with a name. As I
> understand it, that is a realisation of
>
> FunctionExpression :
> function Identifier opt ( FormalParameterList opt ) { FunctionBody }
>
> in which the optional Identifier (the "name") exists.
>
>> I suggest you to and read the ECMA-262 specification for "Function
>> Definition".
>
> I have, just in case, but I didn't need to: my memory was quite accurate.
>

Then what is wrong with an implementation treating a FunctionExpression
as a Function Definition? And if the answer is nothing (which is the
correct answer) then why insist Microsoft got that wrong?

Johannes Baagoe

unread,
Apr 20, 2010, 3:38:41 PM4/20/10
to
Stefan Weiss :

> Didn't you say (in a different thread) that you "quite liked" Jorge's
> loop() function? That's a named function expression, too. It doesn't
> have to be - you could just call loop() separately from its definition -
> but the way you're using it on
>
> http://baagoe.com/en/RandomMusings/javascript/time.js
>
> it's still a named function expression.

Touché. You are right about that one. I shall correct the matter forthwith.

> Do you deserve a terrible fate now? ;-)

Well, yes: having to confess that my behaviour does not always match my
words :) And publicly, too.

--
Johannes

Stefan Weiss

unread,
Apr 20, 2010, 4:14:11 PM4/20/10
to
On 20/04/10 21:12, Johannes Baagoe wrote:
> Stefan Weiss :
>> and when you want to recurse from inside a function expression.
>
> What is wrong with
>
> var fact = function(n) {
> if (n > 0) {
> return n * fact(n - 1);
> } else {
> return 1;
> }
> };
>
> ?

It works, of course, but it makes the recursion dependent on a
(potentially unrelated) variable from an outer scope. I don't think the
implementation of a function should need to care about which variable it
will be assigned to. And then there are the "self-executing" functions
from your original examples, which run before their result is assigned
to a variable:

var foo = (function () {
// what if I want to recurse here?
})();

BTW, I prefer this style of parenthesis placement, but I think both are
fine as long as the intention is clear.


--
stefan

Johannes Baagoe

unread,
Apr 20, 2010, 3:12:31 PM4/20/10
to
Stefan Weiss :

> Names for function expressions are useful in at least
> two cases: for debugging/profiling,

That could indeed be the case with some debuggers/profilers, I would
consider them less than satisfactory. But see below.

> and when you want to recurse from inside a function expression.

What is wrong with

var fact = function(n) {
if (n > 0) {
return n * fact(n - 1);
} else {
return 1;
}
};

?

> The only alternative for the second case would be arguments.callee,
> which (I think) has recently been deprecated.

I think I just provided another and possibly better alternative.

--
Johannes

Johannes Baagoe

unread,
Apr 20, 2010, 3:28:58 PM4/20/10
to
Garrett Smith :
> Johannes Baagoe :
>>> nick :

>>>> "Some JavaScript engines, not including SpiderMonkey, incorrectly
>>>> treat any function expression with a name as a function definition"

>> In a sort of lame defence (why on earth am I trying to excuse
>> Microsoft?),

> If you're asking me to guess, I would say that you have probably


> mistaken "function definition" with "function declaration".

I hope not. I talk about a function expression with a name. As I
understand it, that is a realisation of

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

in which the optional Identifier (the "name") exists.

> I suggest you to and read the ECMA-262 specification for "Function
> Definition".

I have, just in case, but I didn't need to: my memory was quite accurate.

--
Johannes

Stefan Weiss

unread,
Apr 20, 2010, 2:38:49 PM4/20/10
to
On 20/04/10 20:08, Johannes Baagoe wrote:
> Jorge :
>> Johannes Baagoe :

>>> In a sort of lame defence (why on earth am I trying to excuse
>>> it may be argued that function expressions with a name are
>>> a Really Bad Idea from the beginning, and that anyone who uses them
>>> deserves... well, some terrible fate.
>
>> Huh ?
>> How so ?
>
> var fibonacci = (function() {
> var a = 1; var b = 1;
> return function() {
> a = b - a;
> return b += a;
> };
> }());
>
> is fine.
>
> var fibonacci = (function fib() {
> var a = 1; var b = 1;
> return function() {
> a = b - a;
> return b += a;
> };
> }());
>
> or
>
> var fibonacci = (function() {
> var a = 1; var b = 1;
> return function fib() {
> a = b - a;
> return b += a;
> };
> }());
>
> or (even worse)
>
> var fibonacci = (function fib() {
> var a = 1; var b = 1;
> return function fib() {
> a = b - a;
> return b += a;
> };
> }());
>
> are useless and confusing - what is fib ?

Well, don't write useless and confusing code, then :)

The returned inner function in your examples doesn't need a name, so you
don't give it one. Names for function expressions are useful in at least
two cases: for debugging/profiling, and when you want to recurse from
inside a function expression. The only alternative for the second case


would be arguments.callee, which (I think) has recently been deprecated.

Even if it hasn't: making use of the arguments object has a noticeable
performance penalty in modern browsers.


--
stefan

Garrett Smith

unread,
Apr 20, 2010, 2:37:17 PM4/20/10
to
Johannes Baagoe wrote:
> Jorge :
>> nick :
>
>>> "Some JavaScript engines, not including SpiderMonkey, incorrectly treat
>>> any function expression with a name as a function definition"
>
That behavior, as descriped, is not incorrect.

>> LOL. And these engines are made by Microsoft and are called JScript and
>> are the ones used in each and every Internet Explorer, up to and
>> including the current, latest one.
>>

The behavior described is not incorrect.

>> And they manage miraculously to not only screw up the function
>> expression, but the function declaration too. Wonders of software
>> engineering.
>
> In a sort of lame defence (why on earth am I trying to excuse Microsoft?),

If you're asking me to guess, I would say that you have probably

mistaken "function definition" with "function declaration".

I would also speculate that the author(s) of that (badly written) MDC
page may have had the same mistake (or similar lazy, muddled thinking).

Microsoft may have related bugs, but they are described neither in this
thread nor on MDC.

The MDC page and the responses on this thread (including yours) are an
exhibition of misunderstanding of the specification. How ironic, and
hypocritical now, when the responses on this thread call out Microsoft
for exhibiting a misinterpretation of the specification.

I suggest you to and read the ECMA-262 specification for "Function
Definition".

[...]

VK

unread,
Apr 20, 2010, 2:01:27 PM4/20/10
to
On Apr 20, 5:55 am, Johannes Baagoe <baa...@baagoe.com> wrote:
> Should it be
>
>   (function foo() { /*...*/ })();
>
> or
>
>   (function foo() { /*...*/ }());
>
> (note the place of the closing parenthesis) ?

From the pretty-print point of view I might like the second better as
a fully enclosed construct, without emty parenthesis pending on the
right side. From the other side provokes to try function foo() { /
*...*/ }() which is not correct without an expression context. By its
nature the question is dangerously close to "same line vs. next line
bracket placement" and similar rwar topics :-) so I would just suggest
to use either w/o attacking each other :-)
Please note the different named function handling in IE and other UAs:
in IE

(function foo() { /*...*/ })()

is equivalent (with some subtle details) to:

function foo() { /*...*/ };
foo();

so foo is created and remains in the namespace - the standard test I'm
periodically running to monitor possible changes is at the end of the
post. For the fairness sake IE's behavior equals to Netscape 3.x -4.x:
so the guys went out of business first and then decided that it should
work in some other way.
This is why for FunctionExpression only anonymous functions are
normally used.

> Same question for
>
>   var foo = (function() { /*...*/ })();
>
> vs.
>
>   var foo = (function() { /*...*/ }());
>
> etc.

Same answer as above I guess with the same named functions warning.
Also here parenthesis are not necessary, unlike in the first case:
expression context implied by the function position in right side of
the assignment.

Also note that:

function foo() { /*...*/ }
and
var foo = function foo() { /*...*/ };

are not equal by their internal organization.
In the first case we get one dispid in the name table for
"foo" (spitting 3 times over the shoulder let's say *foo - dispid is
not a *pointer but functionally is a relative of it).
In the second case you get 2 dispids: one for the anonymous function,
the other one for "foo".

So in the first case:
look for foo -> get pointer to the function -> get the function

in the second case:
look for foo -> get pointer to anonymous -> look for anonymous -> get
pointer to the function -> get the function

It is true at least for IE - thus sufficient do not endorse function
assignments as the only way of coding. Yet it is in a big fashion
right now, especially among programmers certified in other languages.
In my office I lock such attempts right away, here I would assign it
to yet another rwar topic :-)


FunctionExpression discrepancies test:

<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

(function foo(){/*NOP*/}())


function demo() {
window.alert(typeof foo);
}


window.onload = function() {
window.setTimeout('demo()',10)
}
</script>
</head>

<body>
<h1>Demo</h1>
</body>
</html>

Johannes Baagoe

unread,
Apr 20, 2010, 2:54:52 PM4/20/10
to
Stefan Weiss :
>>> Johannes Baagoe :

>>>> function expressions with a name are a Really Bad Idea

> The returned inner function in your examples doesn't need a name, so you


> don't give it one.

It seems that we agree, after all.

--
Johannes

Johannes Baagoe

unread,
Apr 20, 2010, 2:08:04 PM4/20/10
to
Jorge :

> Johannes Baagoe :

>> In a sort of lame defence (why on earth am I trying to excuse

>> it may be argued that function expressions with a name are
>> a Really Bad Idea from the beginning, and that anyone who uses them
>> deserves... well, some terrible fate.

> Huh ?
> How so ?

var fibonacci = (function() {

or

or (even worse)

--
Johannes

Stefan Weiss

unread,
Apr 20, 2010, 2:04:37 PM4/20/10
to
On 20/04/10 19:31, Johannes Baagoe wrote:
> In a sort of lame defence (why on earth am I trying to excuse Microsoft?),
> it may be argued that function expressions with a name are a Really Bad
> Idea from the beginning, and that anyone who uses them deserves... well,
> some terrible fate.

Why? The only disadvantage I see are the problems with Microsoft's
botched implementation.

Didn't you say (in a different thread) that you "quite liked" Jorge's
loop() function? That's a named function expression, too. It doesn't
have to be - you could just call loop() separately from its definition -
but the way you're using it on

http://baagoe.com/en/RandomMusings/javascript/time.js

it's still a named function expression.

Do you deserve a terrible fate now? ;-)


--
stefan

VK

unread,
Apr 20, 2010, 5:11:19 PM4/20/10
to
On Apr 20, 10:01 pm, VK <schools_r...@yahoo.com> wrote:
> Also note that:
>
>  function foo() { /*...*/ }
> and
>  var foo = function foo() { /*...*/ };

A copy-past error, please read:

function foo() { /*...*/ }
and
var foo = function() { /*...*/ };

Johannes Baagoe

unread,
Apr 20, 2010, 5:34:15 PM4/20/10
to
Stefan Weiss :
>Johannes Baagoe :

>> var fact = function(n) {
>> if (n > 0) {
>> return n * fact(n - 1);
>> } else {
>> return 1;
>> }
>> };

> It works, of course, but it makes the recursion dependent on a


> (potentially unrelated) variable from an outer scope. I don't think the
> implementation of a function should need to care about which variable it
> will be assigned to.

Good point. One can enclose them in yet another function, though,
but I'm not sure that makes things clearer.

> And then there are the "self-executing" functions from your original
> examples, which run before their result is assigned to a variable:

> var foo = (function () {
> // what if I want to recurse here?
> })();

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.

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.)

--
Johannes

Jorge

unread,
Apr 20, 2010, 5:56:52 PM4/20/10
to
On Apr 20, 8:37 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> (...)

> The MDC page and the responses on this thread (including yours) are an
> exhibition of misunderstanding of the specification. How ironic, and
> hypocritical now, when the responses on this thread call out Microsoft
> for exhibiting a misinterpretation of the specification.
> (...)

The JScript named function expressions BUG (a BUG that's been in each
and every Microsoft Internet Explorer since IE3 up to the greatest and
latest IE8, for **11**YEARS** now, and still counting) can hardly be
considered a "misinterpretation of the specification" wrt to "Chapter
13. Function definitions" of ES-262, 3rd edition, for in the very
first page of that chapter you can read:

"NOTE The Identifier in a FunctionExpression can be referenced from
inside the FunctionExpression's FunctionBody to allow the function to
call itself recursively. However, unlike in a FunctionDeclaration, the
Identifier in a FunctionExpression cannot be referenced from and does
not affect the scope enclosing the FunctionExpression."

How can one possibly misinterpret that ?

If you want to talk hypocritical : loud applause for you.
--
Jorge.

Garrett Smith

unread,
Apr 20, 2010, 6:38:42 PM4/20/10
to
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.

Jorge

unread,
Apr 20, 2010, 6:38:51 PM4/20/10
to
On Apr 20, 8:08 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
> (...)

> are useless and confusing - what is fib ?

I'd just repeat what Stefan has told you already. To recapitulate:

1.- They're not used much due to the named function expressions BUG in
Microsoft's Internet Explorers (in ALL of them).
2.- The function's name is defined inside the function, where it's
safer (and faster too) than in the enclosing scope.
3.- (function functionName () {}).name is === "functionName". So you
can get it from the outside, if you ever need to.

Plus a 4th point of my own:

4.- It's a pity but it's the truth that this BUG and the many others,
long-standing JScript BUGS that Microsoft has been careful not to fix
ever, have had the (intended) effect of spoiling what would have been
otherwise a much nicer language to work with, and with which the web
as a platform could have developed much better and much faster. But as
-unfortunately- that was against Microsoft's own interests, this is
what they've gifted us. It's just another gem of Microsoft's legacy
for the WWW: a functional language with the lambdas badly broken. Make
no mistakes: it's not by coincidence.
--
Jorge.

Johannes Baagoe

unread,
Apr 20, 2010, 6:39:08 PM4/20/10
to
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

VK

unread,
Apr 20, 2010, 6:46:51 PM4/20/10
to
On Apr 21, 1:56 am, Jorge <jo...@jorgechamorro.com> wrote:
> "NOTE The Identifier in a FunctionExpression can be referenced from
> inside the FunctionExpression's FunctionBody to allow the function to
> call itself recursively. However, unlike in a FunctionDeclaration, the
> Identifier in a FunctionExpression cannot be referenced from and does
> not affect the scope enclosing the FunctionExpression."
>
> How can one possibly misinterpret that ?

Easily: please see my post in this thread. NN3 - NN4 did *exactly*
what IE did and does. So the hypocrisy is on some core Mozilla team
members who for years programmed exactly what IE programmed, then
failed and went off the business, then did a new interpretation of the
rule, then started from the scratch with a new browser - so anyone who
managed to stay on the market w/o a break became a standard violator.

For my narrow mind the whole relevant paragraph is bloody idiotic, but
is definitely because of my regular lack of IQ points. Because for me
(expression)
means "do whatever needed to evaluate the expression and return the
result". In this aspect
(function foo(){/*whatever*/}())
is no different: it means "create foo, execute it, set the expression
value to the function return value".

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.
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?


Johannes Baagoe

unread,
Apr 20, 2010, 8:06:07 PM4/20/10
to
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

VK

unread,
Apr 20, 2010, 8:06:42 PM4/20/10
to
On Apr 21, 2:46 am, VK <schools_r...@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.
> 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?

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?

Garrett Smith

unread,
Apr 20, 2010, 8:18:38 PM4/20/10
to
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.
[...]

Stefan Weiss

unread,
Apr 20, 2010, 8:32:11 PM4/20/10
to
On 21/04/10 02:06, VK wrote:
> On Apr 21, 2:46 am, VK <schools_r...@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

Garrett Smith

unread,
Apr 20, 2010, 8:39:10 PM4/20/10
to
Garrett Smith wrote:
> Johannes Baagoe wrote:
>> Garrett Smith :
>>
[...]

> | or FunctionExpression : function Identifier (
> FormalParameterListopt ) { FunctionBody } create a property of the
> variable object whose name
> is the Identifier in the FunctionDeclaration or FunctionExpression,

Sorry about the formatting. I apparently hit Thunderbird's "send"
keyboard shortcut. I do not recall what that is, but seem to have hit it
while typing, 'cause it got sent.

The full production for JScriptFunction is found in the document
MS-ES3.pdf, linked from the Resources section of the FAQ.

[snip]

RobG

unread,
Apr 20, 2010, 10:58:40 PM4/20/10
to
On Apr 20, 3:05 pm, nick <nick...@fastmail.fm> wrote:

> On Apr 19, 9:55 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
>
> > Same question for
>
> >   var foo = (function() { /*...*/ })();
>
> > vs.
>
> >   var foo = (function() { /*...*/ }());
>
> Those shouldn't need the extra parentheses...
>
>     var foo = function() { /*...*/ }();
>
> ...should be valid.
>
> But nobody ever does that, which makes me think some old(ish) browsers
> might be more picky, especially after reading this:
>
> https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions
> #Function_constructor_vs._function_declaration_vs._function_expression
>
> "Some JavaScript engines, not including SpiderMonkey, incorrectly

> treat any function expression with a name as a function definition"

That article seems quite confused, e.g.

| A function declaration also creates a variable
| with the same name as the function name. Thus,
| unlike those defined by function expressions,
| functions defined by function declarations can be
| accessed by their name in the scope they were
| defined in:
|
| 1. function x() {}
| 2. alert(x); // outputs x serialized into a string

Which is may well be confusing as function expressions exhibit exactly
the same behaviour:

var x = function(){};
alert(x); // outputs x serialized into a string

It goes on with:

| The following example shows how function
| names are not related to variables functions
| are assigned to. If a "function variable"
| is assigned to another value, it will still
| have the same function name:
|
| 1. function foo() {}
| 2. alert(foo); // alerted string contains function name "foo"
| 3. var bar = foo;
| 4. alert(bar); // alerted string still contains function name
"foo"

Of course it does, it's a serialisation of the function declaration so
naturally includes the name. Named function expressions behave exactly
the same:

var x = function y(){};
alert(x); // shows function y() {}


The article seems to be a collection of thoughts about functions,
rather than a structured tutorial about functions. I would not
recommend it to anyone trying to learn ECMAScript.


--
Rob

Garrett Smith

unread,
Apr 20, 2010, 11:41:14 PM4/20/10
to
RobG wrote:
> On Apr 20, 3:05 pm, nick <nick...@fastmail.fm> wrote:
>> On Apr 19, 9:55 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
>>
[...]

>> "Some JavaScript engines, not including SpiderMonkey, incorrectly
>> treat any function expression with a name as a function definition"
>
> That article seems quite confused, e.g.
>
> | A function declaration also creates a variable
> | with the same name as the function name. Thus,
> | unlike those defined by function expressions,
> | functions defined by function declarations can be
> | accessed by their name in the scope they were
> | defined in:
> |
> | 1. function x() {}
> | 2. alert(x); // outputs x serialized into a string
>

That output depends on the behavior of host method `alert`, and the
implementation-dependent behavior for Function.prototype.toString.

> Which is may well be confusing as function expressions exhibit exactly
> the same behaviour:
>
> var x = function(){};
> alert(x); // outputs x serialized into a string
>

That bug was knowingly and deliberately included in ECMAScript 262,
edition 5.

The bug is that the spec says Function.prototype.toString must return a
FunctionDeclaration. Instead, implementations mostly, for user-defined
functions, return a representation of a function, either as a
FunctionExpression or a FunctionDeclaration.

When a function has no identifier, it cannot be considered as a
production for FunctionDeclaration and so the string "function(){}", as
returned by implementations, is not a representation of a
FunctionDeclaraton. I proposed the specification to change to allow
FunctionExpression. I did not see a thoughtful, reasonable response to
that; EOD[1].

[...]

>
> The article seems to be a collection of thoughts about functions,
> rather than a structured tutorial about functions. I would not
> recommend it to anyone trying to learn ECMAScript.
>

It needs some organizational work and technical corrections.

[1]<https://mail.mozilla.org/pipermail/es-discuss/2009-September/009820.html>

Lasse Reichstein Nielsen

unread,
Apr 21, 2010, 1:19:34 AM4/21/10
to
Johannes Baagoe <baa...@baagoe.com> writes:

> 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.

It's worth noticing that the above is not valid ECMAScript. The
content of the if match either FunctionDeclaration or
FunctionExpression, but neither is allowed at that point
(FunctionDeclaration because it is not a Statement, but only a
SourceElement, i.e., it can only occur directly inside a function body
or at top-level, and FunctionExpression because a StatementExpression
may not start with "function").

I.e., it's an ECMAScript extension that Mozilla allows it - as a
"FunctionStatement".
The other browsers that also allow it are also extending ECMAScript,
but probably interpret it slightly differently.

The real problem with IE isn't that it allows the above, but that
this code:
var foo = function bar() { ... };
also leaks "bar" as a variable in the surrounding scope. No other
browser does so.
(I still prefer to use named function expressions for recursion, but
one does have to consider the name in both the internal and external
scope).

...


> 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.

Neither are wrong in extending the syntax to allow your code above.
It's simply an extension, like so many others.

IE is wrong in its implementation of named FunctionExpressions, which
are fully defined in the specification and not subject to "extensions".

> 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.

Correct. That's why they are not allowed at the same places: An
ExpressionStatement may not begin with "function", which means that
a FunctionDeclaration cannot be mistaken for a FunctionExpression,
since the latter is not valid at that point.

> That is a syntactic ambiguity of about the worst sort imaginable.

Oh, this is pretty simple.
Try figuring out how to distinguish divisions, end-of-line comments
and RegExp literals. :)



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

Done.

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

There would also be no easy way to make recursive function expressions.
Using arguments.callee sucks (both performance-wise and readability-wise).

/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

VK

unread,
Apr 21, 2010, 5:25:00 AM4/21/10
to
> > 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?

"when you assign to an undeclared identifier: it becomes a property of

the global object" - right

And when you execute an undeclared named function: it has to be first
created so becomes a property of the global object just like above.
One cannot execute something w/o having it first.
My point being is that JavaScript has function-level scope visibility,
not expression-level scope visibility. This way (expression) doesn't
affect the scope, only {function} does.
It was decided to make an exception for FunctionExpression - fine, but
why it is called obvious and natural - remains a mystery to me.

Jorge

unread,
Apr 21, 2010, 7:00:00 AM4/21/10
to
On Apr 21, 2:06 am, Johannes Baagoe <baa...@baagoe.com> wrote:
> 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.

Neither do I.

But as so many people have wasted countless hours in trying to spot,
comprehend and devise workarounds for each and every of Microsoft's
Internet Explorer BUGS, because they (thought they) had to, even
today, when you browse this group's archive, you'll see that most of
the regulars equate one's knowledge of JS to one's knowledge of
Microsoft IE's bugs (*) and workarounds and its many other -countless-
bizarre behaviours. It's pitiful. And it's been a severe drag in
moving the web forward. And still is.

As a consequence, whenever you post code with a named function
expression, some cleverer regular jumps in to "correct" it.

(*)E.g.: most regulars here assume `window` to be a host object. LOL.
--
Jorge.

Johannes Baagoe

unread,
Apr 21, 2010, 8:48:15 AM4/21/10
to
Garrett Smith :
> Johannes Baagoe :

>> 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.

Of course. 51090942171709440000 is much more efficient.

But that isn't the point. I try to figure out whether there are cases
where function expressions need be named, or at least are better named.
My starting position is (or was) "No, named functions are creatures
of the darkness - their syntax sucks by mixing two notions in a way
that is bound create to confusion, for no benefit at all". (And Microsoft
has *nothing* to do with the matter, I didn't suspect that *other*
objections to named function expressions were part of a holy war.)

However, as Stefan Weiss and others rightly point out, there appears
to be at least one case where names for function expressions are
definitely useful: when the function expression calls itself. There
are alternatives, but they are not clearly better, and in the case
of my rather quixotic attempt above, clearly worse.

--
Johannes

Scott Sauyet

unread,
Apr 21, 2010, 9:34:17 AM4/21/10
to
Johannes Baagoe wrote:
> [ ... ] I try to figure out whether there are cases

> where function expressions need be named, or at least are better named.
> My starting position is (or was) "No, named functions are creatures
> of the darkness - their syntax sucks by mixing two notions in a way
> that is bound create to confusion, for no benefit at all". (And Microsoft
> has *nothing* to do with the matter, I didn't suspect that *other*
> objections to named function expressions were part of a holy war.)
>
> However, as Stefan Weiss and others rightly point out, there appears
> to be at least one case where names for function expressions are
> definitely useful: when the function expression calls itself. There
> are alternatives, but they are not clearly better, and in the case
> of my rather quixotic attempt above, clearly worse.

The holy war you mentioned is important here, though. Although named
function expressions are very useful, some Microsoft bugs make them
much less useful than they should be in this case.

The article by kangax [1] explains the issues in detail. But in
brief, here's some IE results:

typeof g; // "function"
var f = function g(){};
f === g; // false
f.expando = 'foo';
g.expando; // undefined

the reference g escapes the function, and appears even before the
declaration, and f and g are not two separate references to the same
function, but two distinct functions!

I'm not sure of the rationale that deprecated arguments.callee, but
that was the other alternative in these cases; I'm not sure what we're
left with now besides terrible hacks like the one you presented and
rejected.

-- Scott
____________________
[1] http://yura.thinkweb2.com/named-function-expressions/

Johannes Baagoe

unread,
Apr 21, 2010, 9:35:14 AM4/21/10
to
Lasse Reichstein Nielsen :
> Johannes Baagoe :

>> MDC's bone of contention is this:
>>
>> if (0) {
>> function zero() {
>> document.writeln("This is zero.");
>> }
>> }

> It's worth noticing that the above is not valid ECMAScript.


> The content of the if match either FunctionDeclaration or
> FunctionExpression, but neither is allowed at that point
> (FunctionDeclaration because it is not a Statement, but only a
> SourceElement, i.e., it can only occur directly inside a function body
> or at top-level, and FunctionExpression because a StatementExpression
> may not start with "function").

Aha. Now that, I understand. It did seem curious to define functions
conditionally in this `#ifdef`-like way.

> I.e., it's an ECMAScript extension that Mozilla allows it - as a
> "FunctionStatement".

> The other browsers that also allow it are also extending ECMAScript, but
> probably interpret it slightly differently.

I see that 5th ed. addresses the problem: (12)

NOTE Several widely used implementations of ECMAScript are known to
support the use of FunctionDeclaration as a Statement. However there
are significant and irreconcilable variations among the implementations
in the semantics applied to such FunctionDeclarations. Because of
these irreconcilable difference, the use of a FunctionDeclaration
as a Statement results in code that is not reliably portable among
implementations.

IOW, avoid, unless for personal use or strictly controled intranets.
Even there, it is hard to see any real benefit. If different functions
are needed according to flags (say, various versions of an `assert`
function for debugging), assign them to the same variable in conditions
at the start of the code.

[Very clear explanation of when "function foo() {}" is a function
declaration, and when it is a function expression - many thanks !]

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

> There would also be no easy way to make recursive function
> expressions. Using arguments.callee sucks (both performance-wise
> and readability-wise).

One could assign the function to a variable in the enclosing scope,
but I have to agree that it useful to be able simply to name the
function for the benefit of its internal scope.

--
Johannes

Richard Cornford

unread,
Apr 21, 2010, 9:56:53 AM4/21/10
to
Lasse Reichstein Nielsen wrote:
>> MDC's bone of contention is this:
>>
>> if (0) {
>> function zero() {
>> document.writeln("This is zero.");
>> }
>> }
<snip>

> The real problem with IE isn't that it allows the above, but
> that this code:
> var foo = function bar() { ... };
> also leaks "bar" as a variable in the surrounding scope.
> No other browser does so.

That is the problem, but it is not the full extent of the problem. The
function that is referred to by the 'leaked' - bar - is not the same
function object as the one that will be referred to by - foo - following
the evaluation of - foo = function bar() { ... }; -, and - bar - will
exist and refer to its (second/other) function from variable
instantiation onwards. That is, bar exists prior to the evaluation of
the function expression that creates the function object that is
assigned to - foo -, and exists unconditionally (independently of
whether the - foo = function bar() { ... }; - ever actually gets
executed.

> (I still prefer to use named function expressions for recursion,
> but one does have to consider the name in both the internal and
> external scope).

<snip>

Which presumably includes taking into account that if code in the body
of the - foo = function bar() { ... }; - function refers to - bar - and
it is the function object that was created as a result of evaluating the
function expression that is executed, the - bar - references will be
referees to the other function object (the one previously crated during
variable instantiation). I.E. in that context - (bar !=
arguments.callee) - would be true (with implications for the respective
scope chains employed), and any initial call to - bar - would not
actually be recursion.

Richard.

Richard Cornford

unread,
Apr 21, 2010, 9:56:55 AM4/21/10
to
VK wrote:

> On Apr 21, 1:56 am, Jorge wrote:
>> "NOTE The Identifier in a FunctionExpression can be referenced
>> from inside the FunctionExpression's FunctionBody to allow the
>> function to call itself recursively. However, unlike in a
>> FunctionDeclaration, the Identifier in a FunctionExpression
>> cannot be referenced from and does not affect the scope
>> enclosing the FunctionExpression."
>>
>> How can one possibly misinterpret that ?
>
> Easily: please see my post in this thread.

No thank you.

> NN3 - NN4 did *exactly* what IE did and does.

No they didn't. For a start function expressions were introduced into
JavaScript(tm) in version 1.2 (possibly even 1.3), which means that
Netscape Navigator 3 could not treat function expressions the same way
as JScript does, as it had none to treat in any way. Netscape Navigator
4 did not create 2 distinct function objects in association with
evaluating a named function expression, so that is not "*exactly* what
IE did" either.

> So the hypocrisy is ... .

Evident.

> For my narrow mind the whole relevant paragraph is bloody idiotic,
> but is definitely because of my regular lack of IQ points.

It is your problems with achieving a rational thought process that is
the problem.

> Because for me (expression) means "do whatever needed to evaluate
> the expression and return the result".

Which is far too imprecise to be of any use to anyone.

> In this aspect
> (function foo(){/*whatever*/}())
> is no different: it means "create foo,
> execute it, set the expression
> value to the function return value".
>
> This IE's behavior is won't-fix anyway,

They might. The creation of the additional function object really isn't
that sensible/useful a thing to be doing.

> so not a bug but a peculiarity (aka a feature), so interesting
> for a theoretical discussion only.
> 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

What do you imagine pissed them off? Finding that - (foo !== bar) - is
true in JScript when - typeof - both - foo - and - bar - is still
'function' seems like a good reason.

> var a = (b = 1);
> window.alert(a);
> window.alert(b); // 1
>keeps them relaxed?

Well, in that case - (a !== b) - is false.

Richard.

Richard Cornford

unread,
Apr 21, 2010, 9:56:52 AM4/21/10
to
VK wrote:
>>> 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?
>
> "when you assign to an undeclared identifier: it becomes a property
> of the global object" - right
>
> And when you execute an undeclared named function: it has to be
> first created

Evaluating a function expression should result in the creation of a
function object, which then must then 'exist' and have some
manifestation that occupies memory somewhere on the computer.

> so becomes a property of the global object

Not so. The creation of any object (function or otherwise) does not
necessitate the creation of, or assignment to, properties of the global
object.

> just like above.

The above case shows a function declaration in the global execution
context, which will result in the creation of a property of the global
object, as the global object is used as the Variable object for the
global execution context. A function declaration in a function execution
context will result in the creation of a property of the function
execution context' Variable object (which is never the global object).

Function expressions, as opposed to declarations, need not result in the
creation of any properties of any objects at all. And the IE/JScript bug
that results in named function expressions being additionally processed
as function declarations causes the additional function that is created
to be assigned to a property of the Variable object of the execution
context in which the expression is located, which will only be the
global object for the global execution context.

> One cannot execute something w/o having it first.

True, but "having" something does not require that it be assigned to a
property of any object in javascript, and so certainly does not require
that it "becomes a property of the global object".

> My point

You have a point?

> being is that JavaScript has function-level scope
> visibility, not expression-level scope visibility.
> This way (expression) doesn't affect the scope, only
> {function} does.

That is not a point, it is a poorly/vaguely worded statement of fact.

> It was decided to make an exception for FunctionExpression -
> fine,

It wasn't.

> but why it is called obvious and natural -

Who called it that? Why the code you posted does what it does is obvious
("natural" is a slightly perverse term to attempt to apply computer
code); just a matter of understanding the scoping rules for the language
being used.

> remains a mystery to me.

It won't be alone.

Richard.

Richard Cornford

unread,
Apr 21, 2010, 9:57:00 AM4/21/10
to
Scott Sauyet wrote:
<snip>

> I'm not sure of the rationale that deprecated arguments.callee,

In what sense deprecated? The - arguments.callee - property is still
available in ES5, just not in ES5 'strict' mode. It has yet to be
established that ES5 'strict' mode is a suitable/viable language variant
for general purpose browser scripting work, and in the event that it
doesn't turn out to be viable it won't be that widely used and so could
not then form the basis for any ES6+. Thus the future of -
arguents.callee - is probably independent of the future of ES5 'strict',
necessitating any genuine attempt to deprecate it to be associated with
some full ES6+ rather than just an opt-in variant.

> but that was the other alternative in these cases; I'm not sure
> what we're left with now besides terrible hacks like the one you
> presented and rejected.

Mostly inner function declarations probably. If JScript is going to
(additionally) process named function expressions as declarations anyway
then the way back to consistent behaviour might by to deliberately go
for function declarations instead.

Richard.

Richard Cornford

unread,
Apr 21, 2010, 9:56:58 AM4/21/10
to
Johannes Baagoe wrote:
> Garrett Smith :
>> Johannes Baagoe :
>
>>> 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;};
^^^^
As that - fact - is undeclared there is a side effect of creating a
property of the global object and assigning the function to that, in
which case why not a global declared global - fact - function
declaration? The effect would be the same and the code would be simpler.
Of course declaring - fact - as a function local variable in the
surrounding function would work fine, and without the long-term global
side effect. But then, why not an inner function declaration, as in:-

((function() {
function fact(n){


return n > 0 ? n * fact(n - 1) : 1;
}

return fact;
}())(21));

- or the simpler:-

(function(x) {
function fact(n){


return n > 0 ? n * fact(n - 1) : 1;
}

return fact(x);
}(21));

>>> }())(21));
>>>
>>> which is hardly a model of legibility.
>
>> Or design.
>
> Of course. 51090942171709440000 is much more efficient.
>
> But that isn't the point. I try to figure out whether there
> are cases where function expressions need be named,

Which I think must require an example situation where a named function
expression couldn't be replaced with an inner function declaration (that
there be a good reason for not doing so), or a very good argument
against function declarations.

> or at least are better named. My starting position is (or
> was) "No, named functions are creatures of the darkness -
> their syntax sucks by mixing two notions in a way
> that is bound create to confusion, for no benefit at all".

> (And Microsoft has *nothing* to do with the matter, I didn't
> suspect that *other* objections to named function expressions
> were part of a holy war.)

Don't mistake (the better informed) objections to JScript's handling of
named function expressions for a "holy war". What JScript does is hugely
problematic as it appears to 'work' under most circumstance (apparently
you can call a named function expression recursively using its name) but
what actually happens is not what most would think is happening, and so
there is a potential for really unrecognisable bugs to be introduced in
JScript, infrequently but just at the point were scope chain structures
are getting complex.

Of course efficiency and memory use-wise, creating two function objects
in association with the evaluation of any named function expression
isn't such a good idea either, but for most web page scripts that is
hardly going to be noticeable.

> However, as Stefan Weiss and others rightly point out, there
> appears to be at least one case where names for function
> expressions are definitely useful: when the function expression
> calls itself.

Which would be fine if they always did call themselves.

> There are alternatives, but they are not clearly better,

It is not better when the code you write does the same thing in all
javascript environments instead of doing something unique in just one of
them?

> and in the case of my rather quixotic attempt above, clearly
> worse.

At least your example would behave the same under JavaScript(tm) and
JScript.

Richard.

Richard Cornford

unread,
Apr 21, 2010, 9:56:56 AM4/21/10
to
Johannes Baagoe wrote:
> Should it be
>
> (function foo() { /*...*/ })();
>
> or
>
> (function foo() { /*...*/ }());
>
> (note the place of the closing parenthesis) ?
>
> Both are AFAICT syntactically correct and indeed equivalent, but
> I would tend to prefer the latter: since we are warning the future
> reader "Beware! This function is not only defined / declared but
> also called right away!", why not make it quite clear where the
> scope of that warning ends?

As I am responsible for that construct's use in browser scripting I
should probably say something about the positioning of the parenthesise.
There was no reason (good or otherwise) for the 'choice' of putting the
parenthesise round the function expression rather than the whole call
expression. It was probably a case of the thinking about parenthesise
stopping at the point of having something that 'worked', and then the
form of the first examples being re-produced without this aspect being
questioned.

There would have been some influence from structures such as:-

function doSomething(x){
// code that does some 'set-up' on the first
// invocation that does not need to be repeated.

/* Replace the global function with a new one that does the actual
work, and call that function so that the work gets done along
with the 'set-up' on the first invocation of - doSomething -.
*/
(doSomething = function(n){
// code that does whatever without repeating the 'set-up'.
})(x);
}

- which were not uncommon at the time (at least in some circles), and
where - (x = function(){ ... }()); - is not a viable substitute
(though - ((x = function(){ ... })()); - would have been fine). Today I
would probably split the last statement above into two and have a simple
assignment of the function followed by an explicit call to -
doSomething - as a second statement. (Experience having had the effect
of prompting a bias towards code readability over the convolutions that
some label "elegance" these days).

So, parenthesise around the whole call expression; why not?

> Same question for
>
> var foo = (function() { /*...*/ })();
>
> vs.
>
> var foo = (function() { /*...*/ }());
>

> etc.

Again; why not?

> It doesn't matter much when `foo` is called with an empty list
> of arguments, but I believe it would make cases where its
> arguments are complex much clearer - any editor that matches
> opening and closing parentheses would immediately show the various
> parts of the construct.

I don't think that works as an argument. Wouldn't such an editor's
ability to match parenthesises make sorting out the scope of complex
arguments fairly simple in any case, given that the call surrounds the
arguments with a pair of them?

> Are there better arguments in favour of the former ?

Better? Are there any real arguments for the former, beyond habit,
fashion, etc? Not that those can be entirely dismissed as oft-used
structures can become easily recognised/understood by virtue of their
familiarity.

Richard.

Ry Nohryb

unread,
Apr 21, 2010, 10:14:48 AM4/21/10
to
On Apr 20, 11:34 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
> (...)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));

(function (fact) {


return fact= function (n) {
return n > 0 ? n * fact(n - 1) : 1;
};

})()(21)

Note how clearly and unequivocally "()()" reveals two consecutive
function calls, much more than a muddy "())())".
And "fact" was a global in yours.
--
Jorge.

Scott Sauyet

unread,
Apr 21, 2010, 10:30:44 AM4/21/10
to
Richard Cornford wrote:

> Scott Sauyet wrote:
>> I'm not sure of the rationale that deprecated arguments.callee,
>
> In what sense deprecated? The - arguments.callee - property is still
> available in ES5, just not in ES5 'strict' mode. [ ... ]

I suppose that the only sense in which it's deprecated is just that:
there is a suggestion that some strict mode of operations is in some
way better; that mode does not include arguments.callee. I haven't
paid close attention yet to strict mode. But I did assume that it was
intended as the basis for a newer specification that was considered in
some way superior.

I'm curious as to the rationale for leaving arguments.callee out of
strict mode, though. Do you have any pointers to the reasons behind
this?


>> but that was the other alternative in these cases; I'm not sure
>> what we're left with now besides terrible hacks like the one you
>> presented and rejected.
>
> Mostly inner function declarations probably. If JScript is going to
> (additionally) process named function expressions as declarations anyway
> then the way back to consistent behaviour might by to deliberately go
> for function declarations instead.

Yes, and this does solve the basic problem that the other solutions
were often addressing:

var fact = function(n) {


return n > 0 ? n * fact(n - 1) : 1;
}

var g = fact;
fact = null; // g now does not work.


With inner functions, we're ok:

var fact = (function() {
function f(n){
return n > 0 ? n * f(n - 1) : 1;
}
return f;
}());
var g = fact;
fact = null; // g still works.


I suppose that is what we have available. But these still seems more
elegant and more immediately comprehensible:

var fact = function f(n)
return n > 0 ? n * f(n - 1) : 1;
}

or

var fact = function(n) {
return n > 0 ? n * arguments.callee(n - 1) : 1;
}

I'll probably continue to use the latter format unless I find a need
to use strict mode or someone can explain what's wrong with
arguments.callee.

--
Scott

Ry Nohryb

unread,
Apr 21, 2010, 10:31:42 AM4/21/10
to
On Apr 21, 4:14 pm, Ry Nohryb <jo...@jorgechamorro.com> wrote:
> On Apr 20, 11:34 pm, Johannes Baagoe <baa...@baagoe.com> wrote:
>
> > (...)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));
>
> (function (fact) {
>   return fact= function (n) {
>     return n > 0 ? n * fact(n - 1) : 1;
>   };
>
> })()(21)


Of course it would still be much better to use a named FE, Microsoft
permitting :

(function fact (n) {


return n > 0 ? n * fact(n - 1) : 1;

})(21)


I find both of them truly beautiful and legible rather than "hardly a
model of legibility".
--
Jorge.

Richard Cornford

unread,
Apr 21, 2010, 11:04:26 AM4/21/10
to
Scott Sauyet wrote:
> Richard Cornford wrote:
>> Scott Sauyet wrote:
>>> I'm not sure of the rationale that deprecated arguments.callee,
>>
>> In what sense deprecated? The - arguments.callee - property is
>> still available in ES5, just not in ES5 'strict' mode. [ ... ]
>
> I suppose that the only sense in which it's deprecated is just
> that: there is a suggestion that some strict mode of operations
> is in some way better; that mode does not include arguments.callee.
> I haven't paid close attention yet to strict mode. But I did
> assume that it was intended as the basis for a newer specification
> that was considered in some way superior.

Very much intended as the basis for newer specification (with an
intention to define new 'syntactic sugar' only in terms of strict mode
code (rather than written algorithms)), and considered, in some sense,
'superior' by its creators. However, the dearth of actual browser
scripting experience among the members of the ECMA committee (their
being mostly language experts and implementers) suggests a need to test
their creation against its ability to solve browser-scripting problems
before accepting it as 'superior'.

> I'm curious as to the rationale for leaving arguments.callee out
> of strict mode, though. Do you have any pointers to the reasons
> behind this?

Well, - arguments.callee - is pretty redundant in a correct ES5
implementation as named function expressions (or at least the function
objects resulting from their evaluation) can call themselves recursively
by name.

>>> but that was the other alternative in these cases; I'm not sure
>>> what we're left with now besides terrible hacks like the one you
>>> presented and rejected.
>>
>> Mostly inner function declarations probably. If JScript is going to
>> (additionally) process named function expressions as declarations
>> anyway then the way back to consistent behaviour might by to
>> deliberately go for function declarations instead.
>
> Yes, and this does solve the basic problem that the other solutions
> were often addressing:
>
> var fact = function(n) {
> return n > 0 ? n * fact(n - 1) : 1;
> }
> var g = fact;
> fact = null; // g now does not work.

I am never convinced that solving the problem of people later writing
code that screws something up is a problem worth solving. The potential
for writing code that screws things up always will far exceed any
ability to defend against it, so if someone wants to do that they will
manage it one way or another, and if they didn't want to they will (or
should) observe that they have broken something and so go back an change
their code so that it works correctly in context.

> With inner functions, we're ok:
>
> var fact = (function() {
> function f(n){
> return n > 0 ? n * f(n - 1) : 1;
> }
> return f;
> }());
> var g = fact;
> fact = null; // g still works.
>
>
> I suppose that is what we have available. But these still seems more
> elegant and more immediately comprehensible:
>
> var fact = function f(n)
> return n > 0 ? n * f(n - 1) : 1;
> }
>
> or
>
> var fact = function(n) {
> return n > 0 ? n * arguments.callee(n - 1) : 1;
> }
>
> I'll probably continue to use the latter format unless I find a need
> to use strict mode or someone can explain what's wrong with
> arguments.callee.

The main argument against - arguments.callee - is - arguments -. It has
been observed that there are implementations that do not create an -
arguments - object if your code does not refer to - arguments -(after
all, you cannot tell the difference in those cases so the required
behaviour is still there). This is more efficient at runtime (as it is
one fewer object to create/set-up for each function call), and so might
be a good thing to encourage.

Richard.

Johannes Baagoe

unread,
Apr 21, 2010, 11:22:23 AM4/21/10
to
Scott Sauyet :

> I'm not sure what we're left with now besides terrible hacks like
> the one you presented and rejected.

At this point, I would say:

1. Declare the functions when there is no good reason for using
function expressions. (Mere pursuit of cuteness does not qualify as
a good reason, except for recreational purposes.)

Thus, Richard Cornford's

(function(x) {
function fact(n) {


return n > 0 ? n * fact(n - 1) : 1;
}

return fact(x);
}(21));

2. If function declarations are undesirable (e.g., for didactic
reasons), assign the inner function to a variable in the outer
function's scope:

(function(x) {
var fact = function(n) {


return n > 0 ? n * fact(n - 1) : 1;
}

return fact(x);
}(21));

> [1] http://yura.thinkweb2.com/named-function-expressions/

Very interesting, thanks a lot.

--
Johannes

Johannes Baagoe

unread,
Apr 21, 2010, 11:58:26 AM4/21/10
to
Richard Cornford :
>>> Johannes Baagoe :

>>>> 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;};
> ^^^^
> As that - fact - is undeclared there

Ooops! I wonder how long I shall continue to make that mistake again
and again. Allowing undeclared variables is bad IMHO, but making
them *global* by default is even worse. It is one of the things I still
hate in javascript, with semicolon insertion and a few others.

> But then, why not an inner function declaration, as in:-
>
> ((function() {
> function fact(n){
> return n > 0 ? n * fact(n - 1) : 1;
> }
> return fact;
> }())(21));
>
> - or the simpler:-
>
> (function(x) {
> function fact(n){
> return n > 0 ? n * fact(n - 1) : 1;
> }
> return fact(x);
> }(21));

Why not, indeed.

>> I try to figure out whether there are cases
>> where function expressions need be named,

> Which I think must require an example situation where a named function
> expression couldn't be replaced with an inner function declaration (that
> there be a good reason for not doing so), or a very good argument
> against function declarations.

I do have an argument against function declarations : use function
expressions from the very beginning in order to expose students to
the notion of functions as first-class objects, and don't confuse
them with another, more traditional approach at the same time.

Whether it qualifies as "good" is of course debatable, not to mention
"very good". Outside of introductory courses in either javascript or
general programming, it is a non-starter.

--
Johannes

Richard Cornford

unread,
Apr 21, 2010, 12:31:51 PM4/21/10
to
Johannes Baagoe wrote:
> Richard Cornford :
>>>> Johannes Baagoe :
>
>>>>> 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;};
>> ^^^^
>> As that - fact - is undeclared there
>
> Ooops! I wonder how long I shall continue to make that mistake
> again and again.

I am still making it from time to time after 9 years of full time
javascript programming. One of the things that JSLint is good for is
that it spots undeclared global property assignments so they are not
that difficult to find and fix.

> Allowing undeclared variables is bad IMHO, but making
> them *global* by default is even worse.
> It is one of the things I still
> hate in javascript, with semicolon insertion and a few
> others.

I assume you mean automatic semicolon insertion (and thinking it a bad
thing that should be abandoned in favor of having the complier complain
about syntax errors). Letting people get into the habit of omitting
semicolons is a bad thing, particularly in the context of this
discussion where:-

(function(){ ... }()) //<-- omitted semicolon
(function(){ ... }())

- has the second parenthesised function expression call turn into an
argument for a call to the first parenthesised function expression
call's result. A (probable) runtime error while the script loads, as the
syntax is fine (and so no automatic semicolon insertion happens between
the two).

<snip>


>>> I try to figure out whether there are cases
>>> where function expressions need be named,
>
>> Which I think must require an example situation where a named
>> function expression couldn't be replaced with an inner function
>> declaration (that there be a good reason for not doing so), or
>> a very good argument against function declarations.
>
> I do have an argument against function declarations : use function
> expressions from the very beginning in order to expose students to
> the notion of functions as first-class objects, and don't confuse
> them with another, more traditional approach at the same time.

Reasonable, but maybe a fact that could be gotten across in a less
dogmatic way.

> Whether it qualifies as "good" is of course debatable, not to mention
> "very good". Outside of introductory courses in either javascript or
> general programming, it is a non-starter.

In reality, most courses in 'javascript' are actually (bad) courses in
browser scripting for the web. In that context not gaining a familiarity
with function declarations would probably be a bad thing. In the context
of an introductory (functional?) programming course that happened to
employ javascript I can see your point.

Richard.

Scott Sauyet

unread,
Apr 21, 2010, 1:02:50 PM4/21/10
to
Richard Cornford wrote:
> Scott Sauyet wrote:

>>    var fact = function(n) {
>>      return n > 0 ? n * fact(n - 1) : 1;
>>    }
>>    var g = fact;
>>    fact = null; // g now does not work.
>
> I am never convinced that solving the problem of people later writing
> code that screws something up is a problem worth solving. The potential
> for writing code that screws things up always will far exceed any
> ability to defend against it, so if someone wants to do that they will
> manage it one way or another, and if they didn't want to they will (or
> should) observe that they have broken something and so go back an change
> their code so that it works correctly in context.

I agree to some degree. But I do believe that reasonable precautions
should be taken. The difficulty lies in determining what might be
reasonable; one person's constant bugaboo is another's ridiculous edge
case.

In fact, a problem much like this bit a friend of mine badly. He of
course didn't simply set the original function to null. He was
building a dynamic environment for the evaluation of various
mathematical functions. He had a variable that represented the
function currently being built by the user, constantly replacing its
value with "new Function(...)" using the code supplied. When the user
was done building and testing the function, it was added to her
environment to be used in building more complex functions. This was
easy to do by creating a new named reference that pointed to the value
of the test function. Then he would reuse the variable that
originally pointed to the function under construction. That worked
fine until he started to allow them to use recursive functions. It
worked fine everywhere but in IE. I helped him figure out why it was
broken, but I don't know how -- or even if -- he ever fixed it.

I'm not saying that his experience is enough of a reason to find a
general solution to the more general issue. But I do think that
there's often not a simple variant of "Then don't do that," that will
answer such questions.

--
Scott

Garrett Smith

unread,
Apr 21, 2010, 2:21:37 PM4/21/10
to
Richard Cornford wrote:
> Johannes Baagoe wrote:
>> Garrett Smith :
>>> Johannes Baagoe :
>>
>>>> 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;};
> ^^^^
> As that - fact - is undeclared there is a side effect of creating a

Mentioned yesterday.

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

Johannes Baagoe

unread,
Apr 21, 2010, 3:11:53 PM4/21/10