473,883 Members | 1,665 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

function syntax question

I feel like it's the twilight zone here as several seemingly trivial
questions are bugging me.

The first of the following three lines is a syntax error, while the
last one is the only one that shows the alert. What is the essential
reason?

function () { alert('hi mom'); }();
function () { alert('hi dad'); }(8);
var x=function () { alert('hi bro'); }();

Csaba Gabor from Vienna

Apr 10 '06 #1
7 1882


Csaba Gabor wrote:
The first of the following three lines is a syntax error, while the
last one is the only one that shows the alert. What is the essential
reason?

function () { alert('hi mom'); }();
function () { alert('hi dad'); }(8);
var x=function () { alert('hi bro'); }();


The grammar as defined in the ECMAScript edition 3 specification knows a
function declaration and a function expression

13 Function Definition
Syntax
FunctionDeclara tion :
function Identifier ( FormalParameter Listopt ) { FunctionBody }
FunctionExpress ion :
function Identifieropt ( FormalParameter Listopt ) { FunctionBody }

where only in the function expression the function name (Identifier) is
optional.

On the right side of the assigment operator you always have an
expression so what you have there will be interpreted as a function
expression.

The other could be made into expressions if you use parentheses e.g.
(function () { alert('hi mom'); }())
--

Martin Honnen
http://JavaScript.FAQTs.com/
Apr 10 '06 #2
Martin Honnen wrote:
Csaba Gabor wrote:
The first of the following three lines is a syntax error, while the
last one is the only one that shows the alert. What is the essential
reason?

function () { alert('hi mom'); }();
function () { alert('hi dad'); }(8);
var x=function () { alert('hi bro'); }();

....
The other could be made into expressions if you use parentheses e.g.
(function () { alert('hi mom'); }())


Fabulous Martin. Thanks for a speedy and clear answer.

In IE 6, the following code shows me that baz is undefined, as I
expected. However, in FF I get a semi random positive integer (usually
in the 30s or 40s). If I were to call window.setTimeo ut with a third
argument, then that is what baz would be. In IE, however, it would
stay undefined.

Should I consider the numeric type and semi random value of baz odd, or
do I deserve what I get because I haven't supplied the extra agrument
to window.setTimeo ut?

window.setTimeo ut(
function () {
return function(baz) {
return function(baz) {
alert("baz: " + typeof(baz) + " " + baz);
}
} ("bar");
} ("foo"), 0);

Apr 10 '06 #3
On 10/04/2006 16:44, Csaba Gabor wrote:
The first of the following three lines is a syntax error, while the
last one is the only one that shows the alert. What is the essential
reason?

function () { alert('hi mom'); }(); ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^

You intend for this to be a function expression, which is fine. However,
the statement as a whole is an expression statement, and they must not
start with either 'function' or '{'.

To define and immediately call a function object created using a
function expression, wrap the latter in parentheses:

(function () {
alert('...');
})();
function () { alert('hi dad'); }(8);
You are being mislead by either Firefox or MSIE (both exhibit the same
behaviour). This is still a syntax error for the same reasons as above.
If you have Opera, evaluate the above and then open the Javascript Console.

As for why this second statement fails to trouble either IE or Fx, they
clearly implement a syntax extension. However, I'm at a loss for what
exactly they consider this to be.

It's unlikely to be a function expression as the parentheses that follow
could be reasonably interpreted as Arguments (thereby inferring a call).
I find it hard to believe that it could be a function declaration, as
one without an identifier doesn't make much sense.

Nevertheless, the different in error behaviour is likely to arise from
the fact the trailing parentheses are considered separate. That is:

function() { ... } /* First statement */
(...); /* Second statement */

In the first case, you present empty parentheses, but that's illegal;
they must contain an expression. In the second, you include a number,
therefore the second statement will be evaluated to that number. In
other words, you might as well have just written the number by itself.
var x=function () { alert('hi bro'); }();


Assignment expressions, including var statement initialisers, can be
function expressions, with or without enclosing parentheses, and can be
called on evaluation.

f = function() {
};

and

f = (function() {
});

are equivalent, as are:

f = function() {
}();

and

f = (function() {
})();

Hope that helps,
Mike

--
Michael Winter
Prefix subject with [News] before replying by e-mail.
Apr 10 '06 #4


Csaba Gabor wrote:

Should I consider the numeric type and semi random value of baz odd,


No, it is kind of odd when you do not expect it, but the reasons
(timeout lateness) are given here:
<https://bugzilla.mozill a.org/show_bug.cgi?id =10637>
I wonder whether the W3C groups currently defining window and
setTimeout/setInterval will consider that issue and either specify that
parameter or specify that it should not be there. So far,
<http://www.w3.org/TR/Window/#timers> does not talk about any parameters
besides the function to call and the delay in milliseconds.
--

Martin Honnen
http://JavaScript.FAQTs.com/
Apr 10 '06 #5
Michael Winter wrote:
To define and immediately call a function object created using a
function expression, wrap the latter in parentheses:

(function () {
alert('...');
})();


Thanks also for your nice reply, Michael, and for your followup to my
second question, Martin (I noticed you submitted that bug report nearly
7(!) years ago). The responses have been very informative. I have a
final question about closures. When I consider the example below, frob
shows a value ("input" as expected), then baz is undefined (as
expected) and then the final alert shows frob as undefined.

var foo = function (baz) {
var res = typeof(frob)==" undefined" ? "" : frob;
alert ("frob: " + typeof(frob) + " " + res); }

function bar() {
return function(baz,fr ob) {
return function(baz) {
alert("frob: " + frob);
alert("baz: " + baz);
foo(); }} (7, "input");
}

bar()();
However, if I now take 'foo' in function bar and replace it with foo's
definition surround by parens (see below), then the third alert will
show me that frob has value "input". My question is: why is there a
difference, and how is it possible to wrap a named function foo
(external to bar, without frob as a named parameter) so that it can be
called within bar and know about non global frob.
function bar() {
return function(baz,fr ob) {
return function(baz) {
alert("frob: " + frob);
alert("baz: " + baz);
(function (baz) {
var res = typeof(frob)==" undefined" ? "" : frob;
alert ("frob: " + typeof(frob) + " " + res); })();
}} (7, "input");
}

bar()();
Regards,
Csaba

Apr 11 '06 #6
"Csaba Gabor" <da*****@gmail. com> writes:
var foo = function (baz) {
var res = typeof(frob)==" undefined" ? "" : frob;
alert ("frob: " + typeof(frob) + " " + res); }

function bar() {
return function(baz,fr ob) {
return function(baz) { .... foo(); }} (7, "input");
}

bar()();
However, if I now take 'foo' in function bar and replace it with foo's
definition surround by parens (see below), then the third alert will
show me that frob has value "input". My question is: why is there a
difference,
That's what closures are all about. When a closure is contained, the
scope chain at that point is stored as part of it, and it is reinserted
when the function is called.
When replacing the "foo" identifier, bound to a closure created in the
global scope, with a function expression, then that function expression
creates a closure containing the scope at that point. That scope contains
the variables frob and baz, which the global scope didn't.
and how is it possible to wrap a named function foo
(external to bar, without frob as a named parameter) so that it can be
called within bar and know about non global frob.
You can't. The scope chain used to resolve variables in the body
of a function is created when the function expression/declaration
is evaluated to a closure. If you want values to be available to
that function body, you must pass them as parameters or store them
in variables that are part of the scope captured in the closure.
return function(baz,fr ob) {
return function(baz) { .... (function (baz) {
var res = typeof(frob)==" undefined" ? "" : frob;
(in scope of "frob" paremeter declared above).
alert ("frob: " + typeof(frob) + " " + res); })();
}} (7, "input");
}


The word "closure" means more than just "first class function".

Lisp has first class functions but dynamic scope, so a function
declaration with a free variable (one not bound by the expression
itself) will use the scope available at the call point, not the
declaration point.

Example (from Emacs Lisp):
(defun foo (x) (lambda (y) (+ x y))) ;; x free var in (lambda (y) (+ x y))
(let ((foo2 (foo 2))
(x 37))
(funcall foo2 4)) ;; yields 41, value of x not kept

Compare that to javascript:
function foo(x) { return function(y) { return x + y; }; }
var foo2 = foo(2);
var x = 37;
alert(foo2(4)); // alerts 6, value of x stored in closure

Ditto for Scheme, a dialect of Lisp with static scope:
(defun foo (x) (lambda (y) (+ x y)))
(let ((foo2 (foo 2))
(x 37))
(foo2 4)) ;; yields 6 too.
The closure contains not only the body of the function, but also the
the free variables. And it's not just their values, it's the actual
variables, as a common error shows:

for (var i = 0; i < 10; i++) {
elems[i].onclick = function() {
alert("You clicked element number " + i);
};
}

Many would expect the above to add ten onclick handlers which each
alert a different number between 0 and 9.
However, no matter which element is clicked, you are told that you
clicked element number 10. That's because all ten closures[1] will
have the same scope chain stored in them, and in that scope chain
is one variable called "i" with the value "10" (after the loop is
done).
The way to avoid this problem is to create ten functions with
either different bodies or different scope chains. Different bodies
would suggest the Function constructor, and managing source code
at runtime is rarely a good idea. The way to create different scope
chains is to make new function calls:

elems[i].onclick = (function (elemNr) {
return function() {
alert("You clicked element number " + elemNr);
};
})(i);

or using the "with" operator:

with ( {elemNr : i} ) {
elems[i].onclick = function() {
alert("You clicked element number " + elemNr);
};
}
/L
[1] Actually, implementations may choose to create only one closure
here, since it knows the ten closures will be indistinguishab le (same
body, same scope chain).
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
'Faith without judgement merely degrades the spirit divine.'
Apr 12 '06 #7
Lasse Reichstein Nielsen wrote:
"Csaba Gabor" <da*****@gmail. com> writes:
var foo = function (baz) {
var res = typeof(frob)==" undefined" ? "" : frob;
alert ("frob: " + typeof(frob) + " " + res); }

function bar() {
return function(baz,fr ob) {
return function(baz) { ...
foo(); }} (7, "input");
}

bar()();
However, if I now take 'foo' in function bar and replace it with foo's
definition surround by parens (see below), then the third alert will
show me that frob has value "input". My question is: why is there a
difference,


That's what closures are all about. When a closure is contained, the
scope chain at that point is stored as part of it, and it is reinserted
when the function is called.


YoW! You know, I've been using closures left and right since I learned
about them in September, 2003 at
http://groups.google.com/group/comp....65d8695faf91d/
but I never ran into this issue before because I've always either used
anonymous function or called named functions with all relevant
parameters passed in the function call. So this notion of named
functions being bound to the environment they were created in never
made it home with me.
When replacing the "foo" identifier, bound to a closure created in the
global scope, with a function expression, then that function expression
creates a closure containing the scope at that point. That scope contains
the variables frob and baz, which the global scope didn't.
and how is it possible to wrap a named function foo
(external to bar, without frob as a named parameter) so that it can be
called within bar and know about non global frob.
You can't. The scope chain used to resolve variables in the body
of a function is created when the function expression/declaration
is evaluated to a closure. If you want values to be available to
that function body, you must pass them as parameters or store them
in variables that are part of the scope captured in the closure.


Yes, that was my conclusion, too, but I wanted to make sure that my
empirical observations were correct. To give some context to the
question...that is, to explain why I asked them...the first two were
offshoots in writing up this last one.

This closure issue came up because I am storing an array of functions
(e.g. an editor needs to respond differently to each command), and then
I want to call each function in context. All of the functions have
been taking a small (ie. 2) number of arguments, one being an optional
repeat count. And this was working fine. I found that I needed to add
a third argument to one of the functions, which is to say that I simply
wanted to have that variable available to the function without passing
it in since I didn't want to put it in the formal parameter list of all
the other functions.

However, I came to the conclusion, as you have confirmed, that this
will not fly, and I didn't like the idea of storing the value as a
property of the function itself, nor of making it global. So, I
decided to make an object onto which I put any variable of interest
(sort of an oApplication object) as a property, and then I always pass
in that object as the single argument to the function that corresponds
to the action that is to be taken.
....
or using the "with" operator:

with ( {elemNr : i} ) {
elems[i].onclick = function() {
alert("You clicked element number " + elemNr);
};
}


I never used with this way...interesti ng...

Thanks again, Lasse, and for everyone contributing to this awesome
thread.
Csaba

Apr 12 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
46971
by: ¤ Alias | last post by:
I have a function named getID3info (lvwDiscInfo.SelectedItem). What is the difference between getID3info (lvwDiscInfo.SelectedItem) and Call getID3info(lvwDiscInfo.SelectedItem) ?
10
1474
by: Ron_Adam | last post by:
I'm trying to figure out how to test function arguments by adding a decorator. @decorate def func( x): # do something return x This allows me to wrap and replace the arguments with my own, but not get the arguments that the original function received.
7
3663
by: MALdito | last post by:
hi everybody let me say right from the start .. I´m not a coder ... "just" a designer! that said .. here is my question: I´m using dreamweaver´s built in preloader for a menu. it looks like this: function MM_preloadImages() { //v3.0 var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array(); var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length;
6
2841
by: Stuart McGraw | last post by:
I am looking for a VBA "format" or "template" function, that is, a function that takes a format string and a varying number of arguments, and substitutes the argument values into the format string as specified in the format string. For example fmt("this is $1 format string. arg2 is $2", "short", 3) would return the string "this is short format string. arg2 is 3" Now, the above is easy to write and I have done so. What I want is...
5
1774
by: Steve Schlesinger | last post by:
Suppose you have class A {}; class B {} template<class T> void SomeFcn( T t ) {…}; A a; B b;
7
3231
by: VK | last post by:
I was getting this effect N times but each time I was in rush to just make it work, and later I coudn't recall anymore what was the original state I was working around. This time I nailed the bastard so posting it before I forgot again... By taking this minimum code: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html> <head>
5
6535
by: Radu | last post by:
Hi. In a repeater I have as ItemTemplate the following, among others, and everything works great: <asp:SqlDataSource ID="LocationSqlDataSource" SelectCommand="SELECT blah-blah-blah" EnableCaching="True" ConnectionString="<%$ ConnectionStrings:OrderingProcess %>" CacheDuration="60" FilterExpression="ID = {0}" RunAt="server">
6
3639
by: vasudevram | last post by:
Hi group, Question: Do eval() and exec not accept a function definition? (like 'def foo: pass) ? I wrote a function to generate other functions using something like eval("def foo: ....") but it gave a syntax error ("Invalid syntax") with caret pointing to the 'd' of the def keyword.
6
3520
by: M Turo | last post by:
Hi, I was wondering if anyone can help. I'm want to pre-load a 'table' of function pointers that I can call using a its arrayed index, eg (non c code example) pFunc = func_A; pFunc = func_B;
0
9779
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11114
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10835
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10407
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7960
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7114
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5787
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5982
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4605
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.