Function expressions vs function declarations: return value - javascript

In a Udacity lesson the difference between function expressions and declarations is explained as follows:
A function declaration defines a function and does not require a
variable to be assigned to it. It simply declares a function, and
doesn't itself return a value ... On the other hand, a function
expression does return a value.
This is confusing; to my knowledge, when both function expressions and function declarations include a return statement, both return a value.
If I understand correctly, the difference with respect to return value is that in a function expression, if a value is changed in the first call of the function, in a subsequent call the updated value would be preserved—whereas if the function were not stored in a variable, the return value would be erased when the function is finished executing. Am I missing something, and is the statement from the lesson accurate?
Note: My question is different from the one marked as a duplicate. In that question it asks what the reasons for using one over the other, but return value is not mentioned in the question or explained in its answers.

To understand what this really is about, we need to dig into the JavaScript grammar:
In ECMAScript a script consists of Statements and Declarations. A Statement can be (amongst others) an ExpressionStatement. Note that ExpressionStatement is explicitly defined as:
ExpressionStatement[Yield, Await]:
[lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]
Expression[+In, ?Yield, ?Await];
This looks really cumbersome, but what it says is that an ExpressionStatement cannot possibly start with the keyword function. So if you just write:
function a() {}
This can never be interpreted as an expression although in other circumstances like
const a = function a() {}
it is an expression. (The right hand side of an assignment operation always must be an expression.)
Now, only expressions evaluate a value, statements do not. This is all the text you quote is saying in a hard to understand way.
A function declaration defines a function and does not require a variable to be assigned to it:
True but redundant. A declaration cannot occur at the right hand-side of an assignment.
It simply declares a function, and doesn't itself return a value ...
Yeah, statements do not evaluate to ("return") a value.
On the other hand, a function expression does return a value.
Sure, like any expression.
See https://www.ecma-international.org/ecma-262/8.0/#prod-StatementList

On the other hand, a function expression does return a value.
This is confusing
Yes indeed. What they actually meant was a function expression evaluates to a (function) value - in contrast to a declaration, which is not an expression but a statement and doesn't evaluate to anything. It has nothing do with the value that the function might return from a call.

The definition isn't talking about the function returning a value, it is talking on how one way of creating a function returns a value (which is the function expression) and another just declares a function (a function declaration).
To help you clarify things, you should understand first what an expression is:
An expression is any valid unit of code that resolves to a value.
One example of an expression would be x = 5, which evaluates to 5.
Another example would be 3 + 2, which also evaluates to 5.
In other words, we could say that both expressions above return a value of 5.
A function expression is just an expression that returns (evaluates to) a function:
// expression
const whatever = function expression() {}
// ^^^^^^^^^^^^^^^^^^^^^^^^ this is the function expression in an assignment statement
A function declaration is not an expression but a statement.
It doesn't need to evaluate to a value. It is just immediately declared:
// declaration
function example() {}
How a function is created (via a declaration or an expression) doesn't affect what the function can return - that capability is the same in both cases.

You are right to say that example is confusing.
Maybe it helps if you think of "return value" in the context of an interpreter? By that I mean, imagine if you were parsing Javascript yourself (as if you were Chrome's v8).
The declaration would just define a new function type and it'd be available for use after declaration.
// declare a function named Declaration
function Declaration() { // stuff }
Now imagine it is instead an expression getting evaluated.
// named function expression
var foo = function FooFunc() { // do stuff }
// anonymous function expression
var foo = function () { // do stuff }
// a self-invoking anonymous function expression (example of a non-variable assingment
// The parentheses make it self-invoking and not a declaration.
(function foo() { console.log('foo'); })() // outputs 'foo' when parsed
+function foo() { console.log('foo'); }(); // same as above
!function foo() { console.log('foo'); }(); // same as above
-function foo() { console.log('foo'); }(); // same as above
~function foo() { console.log('foo'); }(); // same as above
First, sees if an assignment (or self-execution) is going to take place. Do this by checking for const or var or (.
Let's suppose the expression is the variable assignment var foo = function fooFunc() {}.
In this case, the interpreter knows that while you'r defining fooFunc, you also want the result of the definition -- the fooFunc function -- to be the value of foo and so there is a "return value" -- the fooFunc function object -- that needs to be assigned.

This can be difficult to learn at first, but lets try a different approach.
They are not talking about the returned value of a function call, its about the value of the expression (as well explained in the other answers).
You can use the console in the Chrome's Developer Tools to see what each expreassion evaluates to, for example: if you input 10 in the console, this expression will return 10
> 10
< 10
And so on...
> 10 + 5
< 15
> 'Hello world!'
< "Hello world!"
Assigning a value to an variable (not with var, const or let) returns the variable new value, so you can see this in the console:
> n = 10
< 10
> var foo = (n = 10) // also `var foo = n = 10` or `foo = n = 10`
< undefined
> foo
< 10
> n
< 10
> (obj = {}).foo = 'bar'
< "bar"
> obj
< {foo: "bar"}
When we are talking about functions, the declaration of it does not return any value, but a function expression returns a reference to the function created, thats why you can assign it to a variable.
> function foo() { }
< undefined
> (function() { })
< ƒ () { }
Thats why you can do things like:
> (function() { return 'it works!' })()
< "it works!"
> myFunc = function() { return 'also works!' }
< ƒ () { return 'also works!' }
> myFunc()
< "also works!"
Hope this help you undertand. :)

Related

Immediately invoked function expression without using grouping operator

I'm trying to immediately invoke a function without using IIFE pattern (enclosing a function definition inside parentheses). Here I see two scenarios:
When a function declaration is invoked immediately: gives SyntaxError.
When a function expression is invoked immediately: executes successfully.
Example 1: gives SyntaxError
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
Example 2: Executes without any error
// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function
So, I have these doubts:
With this approach, why does it give an error for function declaration but not for function expression?
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
In your code you don't have name for the function that's the reason for syntax error. Even if you would had name it would have thrown error.
function func(){
console.log('x')
}();
The reason is the function declaration doesn't return the values of the function however when you wrap function declaration inside () it forces it be a function expression which returns a value.
In the second example the function() {console.log('Inside the function')} is considered expression because it's on RightHandSide. So it executes without an error.
Is there a way we can immediately invoke a function declaration without using IIFE pattern
You can use + which will make function declaration an expression.
+function(){
console.log('done')
}()
If you don't want to use + and () you can use new keyword
new function(){
console.log('done')
}
Extra
A very interesting question is asked by #cat in the comments. I try to answer it.There are three cases
+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5
+function(){} returns NaN
+ acts as Unary Plus here which parses the value next to it to number. As Number(function(){}) returns NaN so it also returns NaN
(+function(){return 5;})() returns Error
Usually IIFE are created using (). () are used to make a function declaration an expression + is short way for that. Now +function(){} is already an expression which returns NaN. So calling NaN will return error. The code is same as
Number(function(){})()
+function(){return 5;}() returns 5
In the above line + is used to make a statement an expression. In the above example first function is called then + is used on it to convert it to number. So the above line is same as
Number(function(){return 5}())
In the proof of statement "+ runs on after the function is called" Consider the below snippet
console.log(typeof +function(){return '5'}());
So in the above snippet you can see the returned value is string '5' but is converted to number because of +
A function declaration, like
function foo() {
}
defines (and hoists) the variable name foo as a function in the current scope. A function declaration doesn't evaluate to a value; it just does something, a bit like an if does something (rather than evaluate to a value).
You can only invoke values which are functions, eg
<somevalue>()
where somevalue is a variable name that refers to a function.
Note that function declarations require function names, because otherwise there's no variable name to assign the function to - your original
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
throws not because of the () at the end, but because of the lack of a name.
You can put parentheses at the end of a function declaration, as long as there's something inside the parentheses - but these parentheses do not call the function, they evaluate to a value:
function x() {
console.log('Inside the function');
}(console.log('some expression inside parentheses'));
The interpreter sees these as two separate statements, like
function x() {
console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));
The inside of the parentheses gets evaluated and then discarded, since it doesn't get assigned to anything.
(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)
The E in IIFE stands for expression, and without the wrapping parenthesis your function is not evaluated as an expression thus the syntax error.
creating an expression is a way of tricking the interpreter and be able to invoke the function immediatly
(function() {
console.log('Inside the function');
})();
In your example you have a function statement followed by the grouping operator, but it's syntactically incorrect for two reasons, first it doesn't have a name, and second because the grouping operator must have an expression inside it, infact if you add a valid one the error will disappear, still you won't obtain your desired result.
function foo() {
console.log('Inside the function');
}();
function foo() {
console.log('Inside the function');
}(1+2);
In order to invoke something, it has to be a function value, a declaration just declares a name, and does not evaluate to the function value itself, hence you cannot invoke it.
A declaration cannot be invoked for the above reason. You have to end up with an expression somehow, either through assignment or grouping (IIFE). So that is a no.
If you give us more context on why you would want to do that, maybe we can help with suggestions.
Not sure why you would want to do it, but:
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
Well, if for function declaration you mean using the keyword function as in:
function name() { return this.name; }
As far as I know, no. You need the extra parentheses to tell the runtime not to assign the function to a name variable, if I understand this stuff right.
Now, what you actually can do is to use Function as in:
new Function('console.log("ey there")')();
Which will execute the console.log code. No need for IIFE here. But I don't see how this could be better than an IIFE.
you can call in either below ways -
~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()

Function is working when assigned to a variable but throwing SyntaxError when executed by itself

I had an IIFE like this one:
(function a() {
return "b";
}());
Executed in the console, it returns "b".
I removed the first set of parentheses, thinking that this'll make the "a" function global, but still work, and return "b":
function a() {
return "b";
}();
But it throws a SyntaxError:
Uncaught SyntaxError: Unexpected token )
Then, I tried converting the function to an expression by assigning to a variable, and it worked:
var c = function a() {
return "b";
}();
console.log(c); // prints b
Why does this happen? Why is it working as an expression but not by itself?
The second piece of code is not what it looks like.
This code looks like a function that is being immediately executed:
function a() {
return "b";
}()
But in reality, it's just a function declaration followed by an empty expression, which is not allowed:
function a() {
return "b";
}
() // not allowed - empty expression
Ben Alman explains this in his article on IIFE's:
When the parser encounters the function keyword in the global scope or
inside a function, it treats it as a function declaration (statement),
and not as a function expression, by default.
...
While parens placed after an expression indicate that the expression
is a function to be invoked, parens placed after a statement are
totally separate from the preceding statment, and are simply a
grouping operator (used as a means to control precedence of
evaluation).
The grouping operator needs to contain an expression to evaluate. By itself it's of no meaning:
() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20
In IIFE's, the outer parentheses are just a means of forcing the parser to expect an expression.
This is why the expression var c = function() { return "b"; }(); also works; it's because the parser knows to expect an expression because of the assignment to c.
Side Note
Alman also recommends against using self-invoking functions without using the outer parentheses when assigning to variables(i.e. var v = function(){...}()) because it's bad practice:
In cases where the extra “disambiguation” parens surrounding the
function expression are unnecessary (because the parser already
expects an expression), it’s still a good idea to use them when making
an assignment, as a matter of convention.
Such parens typically indicate that the function expression will be
immediately invoked, and the variable will contain the result of the
function, not the function itself. This can save someone reading your
code the trouble of having to scroll down to the bottom of what might
be a very long function expression to see if it has been invoked or
not.

Can we define a "function declaration" also as a "function statement"?

This question born considering the function declarations VS function expressions.
We clearly know that a function declaration have this form
function foo() {
var a = 3;
console.log( a );
}
while a function expression can have this form (appearing like what is known like Immediately invoked function expression)
(function foo() {
var a = 3;
console.log( a );
})()
Looking at the immediately invoked function expression I can just notice the first function (the one used in the function declaration) wrapped in parethesis.
Now, the point is: I know that the grouping operator (most commonly known as "the parethesis" () ) can only contain an expression. If this is true I can't say that the function declaration is also a function statement (because it would be like saying that I have wrapped in parenthesis a statement...).
So, can you give some help, I'm a little confused.
A function declaration is also a function statement? If yes, the function wrapped in parenthesis is a statement or what?
I must clarify that I'm not asking about the difference beetwen a function declaration and a function expression. If I mention them and their differences is just to describe my question that is: a "function declaration" is also a "function statement"?
While the syntax of a function expression is the same as a function declaration, they're not the same thing.
The scope of the name used in function declarations is different from named function expressions. When you write:
function foo() {
var a = 3;
console.log( a );
}
the scope of foo is the enclosing function (or the global environment if this is at top level).
When you write:
(function foo() {
var a = 3;
console.log( a );
})
the scope of foo is just the body of the function.
The parser determines whether it's a function expression or declaration based on the context. Since a statement can't be inside parentheses, putting parentheses around it forces it to be an expression.
In expression hoisting will not happened, but in function statement hoisting is occurred.
In function statement, You can write function definition anywhere in js file before or after function call. JIT compiler will hoisting at top of programming file.
For function expression, JIT compiler will not do as same as function statement, which reads where its occurred. If you try to access function before its defined it will show type error.
IIFE is pattern mostly used to avoid access variable outside function.
callMe(); // Function statement
function callMe(){
return console.log("I am function statement");
}
// callMe2(); // TypeError if you call before expression defined.
var callMe2 = function(){
return console.log("I am function expression");
};
callMe2(); //Function expression call
(function(){
return console.log("I am IIFE");
}());

In JavaScript, Why function expression needs to be in bracket for calling the function [duplicate]

Summary
Can you explain the reasoning behind the syntax for encapsulated anonymous functions in JavaScript? Why does this work: (function(){})(); but this doesn't: function(){}();?
What I know
In JavaScript, one creates a named function like this:
function twoPlusTwo(){
alert(2 + 2);
}
twoPlusTwo();
You can also create an anonymous function and assign it to a variable:
var twoPlusTwo = function(){
alert(2 + 2);
};
twoPlusTwo();
You can encapsulate a block of code by creating an anonymous function, then wrapping it in brackets and executing it immediately:
(function(){
alert(2 + 2);
})();
This is useful when creating modularised scripts, to avoid cluttering up the current scope, or global scope, with potentially conflicting variables - as in the case of Greasemonkey scripts, jQuery plugins, etc.
Now, I understand why this works. The brackets enclose the contents and expose only the outcome (I'm sure there's a better way to describe that), such as with (2 + 2) === 4.
What I don't understand
But I don't understand why this does not work equally as well:
function(){
alert(2 + 2);
}();
Can you explain that to me?
It doesn't work because it is being parsed as a FunctionDeclaration, and the name identifier of function declarations is mandatory.
When you surround it with parentheses it is evaluated as a FunctionExpression, and function expressions can be named or not.
The grammar of a FunctionDeclaration looks like this:
function Identifier ( FormalParameterListopt ) { FunctionBody }
And FunctionExpressions:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
As you can see the Identifier (Identifieropt) token in FunctionExpression is optional, therefore we can have a function expression without a name defined:
(function () {
alert(2 + 2);
}());
Or named function expression:
(function foo() {
alert(2 + 2);
}());
The Parentheses (formally called the Grouping Operator) can surround only expressions, and a function expression is evaluated.
The two grammar productions can be ambiguous, and they can look exactly the same, for example:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
The parser knows if it's a FunctionDeclaration or a FunctionExpression, depending on the context where it appears.
In the above example, the second one is an expression because the Comma operator can also handle only expressions.
On the other hand, FunctionDeclarations could actually appear only in what's called "Program" code, meaning code outside in the global scope, and inside the FunctionBody of other functions.
Functions inside blocks should be avoided, because they can lead an unpredictable behavior, e.g.:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
The above code should actually produce a SyntaxError, since a Block can only contain statements (and the ECMAScript Specification doesn't define any function statement), but most implementations are tolerant, and will simply take the second function, the one which alerts 'false!'.
The Mozilla implementations -Rhino, SpiderMonkey,- have a different behavior. Their grammar contains a non-standard Function Statement, meaning that the function will be evaluated at run-time, not at parse time, as it happens with FunctionDeclarations. In those implementations we will get the first function defined.
Functions can be declared in different ways, compare the following:
1- A function defined with the Function constructor assigned to the variable multiply:
var multiply = new Function("x", "y", "return x * y;");
2- A function declaration of a function named multiply:
function multiply(x, y) {
return x * y;
}
3- A function expression assigned to the variable multiply:
var multiply = function (x, y) {
return x * y;
};
4- A named function expression func_name, assigned to the variable multiply:
var multiply = function func_name(x, y) {
return x * y;
};
Even though this is an old question and answer, it discusses a topic that to this day throws many developers for a loop. I can't count the number of JavaScript developer candidates I've interviewed who couldn't tell me the difference between a function declaration and a function expression and who had no clue what an immediately invoked function expression is.
I'd like to mention, though, one very important thing which is that Premasagar's code snippet wouldn't work even if he had given it a name identifier.
function someName() {
alert(2 + 2);
}();
The reason this wouldn't work is that the JavaScript engine interprets this as a function declaration followed by a completely unrelated grouping operator that contains no expression, and grouping operators must contain an expression. According to JavaScript, the above snippet of code is equivalent to the following one.
function someName() {
alert(2 + 2);
}
();
Another thing I'd like to point out that may be of some use to some people is that any name identifier you provide for a function expression is pretty much useless in the context of the code except from within the function definition itself.
var a = function b() {
// do something
};
a(); // works
b(); // doesn't work
var c = function d() {
window.setTimeout(d, 1000); // works
};
Of course, using name identifiers with your function definitions is always helpful when it comes to debugging code, but that's something else entirely... :-)
Great answers have already being posted. But I want to note that function declarations return an empty completion record:
14.1.20 - Runtime Semantics: Evaluation
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
Return NormalCompletion(empty).
This fact is not easy to observe, because most ways of attempting to get the returned value will convert the function declaration to a function expression. However, eval shows it:
var r = eval("function f(){}");
console.log(r); // undefined
Calling an empty completion record makes no sense. That's why function f(){}() can't work. In fact the JS engine does not even attempt to call it, the parentheses are considered part of another statement.
But if you wrap the function in parentheses, it becomes a function expression:
var r = eval("(function f(){})");
console.log(r); // function f(){}
Function expressions return a function object. And therefore you can call it: (function f(){})().
In javascript, this is called Immediately-Invoked Function Expression (IIFE) .
In order to make it a function expression you've to:
enclose it using ()
place a void operator before it
assign it to a variable.
Otherwise it will be treated as function definition and then you won't be able to call/invoke it at the same time by the following way:
function (arg1) { console.log(arg1) }();
The above will give you error. Because you can only invoke a function expression immediately.
This can be achieved couple of ways:
Way 1:
(function(arg1, arg2){
//some code
})(var1, var2);
Way 2:
(function(arg1, arg2){
//some code
}(var1, var2));
Way 3:
void function(arg1, arg2){
//some code
}(var1, var2);
way 4:
var ll = function (arg1, arg2) {
console.log(arg1, arg2);
}(var1, var2);
All above will immediately invoke the function expression.
I have just another small remark. Your code will work with a small change:
var x = function(){
alert(2 + 2);
}();
I use the above syntax instead of the more widely spread version:
var module = (function(){
alert(2 + 2);
})();
because I didn't manage to get the indentation to work correctly for javascript files in vim. It seems that vim doesn't like the curly braces inside open parenthesis.
(function(){
alert(2 + 2);
})();
Above is valid syntax because anything passed inside parenthesis is consider as function expression.
function(){
alert(2 + 2);
}();
Above is not valid syntax. Because java script syntax parser looks for function name after function keyword since it doesn't find anything it throws an error.
Perhaps the shorter answer would be that
function() { alert( 2 + 2 ); }
is a function literal that defines an (anonymous) function. An additional ()-pair, which is interpreted as an expression, is not expected at toplevel, only literals.
(function() { alert( 2 + 2 ); })();
is in an expression statement that invokes an anonymous function.
They can be used with parameters-arguments like
var x = 3;
var y = 4;
(function(a,b){alert(a + b)})(x,y)
would result as 7
Those extra parenthesis creates extra anonymous functions between global namespace and anonymous function that contains the code. And in Javascript functions declared inside other functions can only access namespace of parent function that contains them. As there is extra object (anonymious function) between global scope and actual code scoping is not retained.
You can also use it like:
! function() { console.log('yeah') }()
or
!! function() { console.log('yeah') }()
! - negation op converts the fn definition to fn expression, therefore, you can invoke it immediately with (). Same as using 0,fn def or void fn def

Explain the encapsulated anonymous function syntax

Summary
Can you explain the reasoning behind the syntax for encapsulated anonymous functions in JavaScript? Why does this work: (function(){})(); but this doesn't: function(){}();?
What I know
In JavaScript, one creates a named function like this:
function twoPlusTwo(){
alert(2 + 2);
}
twoPlusTwo();
You can also create an anonymous function and assign it to a variable:
var twoPlusTwo = function(){
alert(2 + 2);
};
twoPlusTwo();
You can encapsulate a block of code by creating an anonymous function, then wrapping it in brackets and executing it immediately:
(function(){
alert(2 + 2);
})();
This is useful when creating modularised scripts, to avoid cluttering up the current scope, or global scope, with potentially conflicting variables - as in the case of Greasemonkey scripts, jQuery plugins, etc.
Now, I understand why this works. The brackets enclose the contents and expose only the outcome (I'm sure there's a better way to describe that), such as with (2 + 2) === 4.
What I don't understand
But I don't understand why this does not work equally as well:
function(){
alert(2 + 2);
}();
Can you explain that to me?
It doesn't work because it is being parsed as a FunctionDeclaration, and the name identifier of function declarations is mandatory.
When you surround it with parentheses it is evaluated as a FunctionExpression, and function expressions can be named or not.
The grammar of a FunctionDeclaration looks like this:
function Identifier ( FormalParameterListopt ) { FunctionBody }
And FunctionExpressions:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
As you can see the Identifier (Identifieropt) token in FunctionExpression is optional, therefore we can have a function expression without a name defined:
(function () {
alert(2 + 2);
}());
Or named function expression:
(function foo() {
alert(2 + 2);
}());
The Parentheses (formally called the Grouping Operator) can surround only expressions, and a function expression is evaluated.
The two grammar productions can be ambiguous, and they can look exactly the same, for example:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
The parser knows if it's a FunctionDeclaration or a FunctionExpression, depending on the context where it appears.
In the above example, the second one is an expression because the Comma operator can also handle only expressions.
On the other hand, FunctionDeclarations could actually appear only in what's called "Program" code, meaning code outside in the global scope, and inside the FunctionBody of other functions.
Functions inside blocks should be avoided, because they can lead an unpredictable behavior, e.g.:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
The above code should actually produce a SyntaxError, since a Block can only contain statements (and the ECMAScript Specification doesn't define any function statement), but most implementations are tolerant, and will simply take the second function, the one which alerts 'false!'.
The Mozilla implementations -Rhino, SpiderMonkey,- have a different behavior. Their grammar contains a non-standard Function Statement, meaning that the function will be evaluated at run-time, not at parse time, as it happens with FunctionDeclarations. In those implementations we will get the first function defined.
Functions can be declared in different ways, compare the following:
1- A function defined with the Function constructor assigned to the variable multiply:
var multiply = new Function("x", "y", "return x * y;");
2- A function declaration of a function named multiply:
function multiply(x, y) {
return x * y;
}
3- A function expression assigned to the variable multiply:
var multiply = function (x, y) {
return x * y;
};
4- A named function expression func_name, assigned to the variable multiply:
var multiply = function func_name(x, y) {
return x * y;
};
Even though this is an old question and answer, it discusses a topic that to this day throws many developers for a loop. I can't count the number of JavaScript developer candidates I've interviewed who couldn't tell me the difference between a function declaration and a function expression and who had no clue what an immediately invoked function expression is.
I'd like to mention, though, one very important thing which is that Premasagar's code snippet wouldn't work even if he had given it a name identifier.
function someName() {
alert(2 + 2);
}();
The reason this wouldn't work is that the JavaScript engine interprets this as a function declaration followed by a completely unrelated grouping operator that contains no expression, and grouping operators must contain an expression. According to JavaScript, the above snippet of code is equivalent to the following one.
function someName() {
alert(2 + 2);
}
();
Another thing I'd like to point out that may be of some use to some people is that any name identifier you provide for a function expression is pretty much useless in the context of the code except from within the function definition itself.
var a = function b() {
// do something
};
a(); // works
b(); // doesn't work
var c = function d() {
window.setTimeout(d, 1000); // works
};
Of course, using name identifiers with your function definitions is always helpful when it comes to debugging code, but that's something else entirely... :-)
Great answers have already being posted. But I want to note that function declarations return an empty completion record:
14.1.20 - Runtime Semantics: Evaluation
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
Return NormalCompletion(empty).
This fact is not easy to observe, because most ways of attempting to get the returned value will convert the function declaration to a function expression. However, eval shows it:
var r = eval("function f(){}");
console.log(r); // undefined
Calling an empty completion record makes no sense. That's why function f(){}() can't work. In fact the JS engine does not even attempt to call it, the parentheses are considered part of another statement.
But if you wrap the function in parentheses, it becomes a function expression:
var r = eval("(function f(){})");
console.log(r); // function f(){}
Function expressions return a function object. And therefore you can call it: (function f(){})().
In javascript, this is called Immediately-Invoked Function Expression (IIFE) .
In order to make it a function expression you've to:
enclose it using ()
place a void operator before it
assign it to a variable.
Otherwise it will be treated as function definition and then you won't be able to call/invoke it at the same time by the following way:
function (arg1) { console.log(arg1) }();
The above will give you error. Because you can only invoke a function expression immediately.
This can be achieved couple of ways:
Way 1:
(function(arg1, arg2){
//some code
})(var1, var2);
Way 2:
(function(arg1, arg2){
//some code
}(var1, var2));
Way 3:
void function(arg1, arg2){
//some code
}(var1, var2);
way 4:
var ll = function (arg1, arg2) {
console.log(arg1, arg2);
}(var1, var2);
All above will immediately invoke the function expression.
I have just another small remark. Your code will work with a small change:
var x = function(){
alert(2 + 2);
}();
I use the above syntax instead of the more widely spread version:
var module = (function(){
alert(2 + 2);
})();
because I didn't manage to get the indentation to work correctly for javascript files in vim. It seems that vim doesn't like the curly braces inside open parenthesis.
(function(){
alert(2 + 2);
})();
Above is valid syntax because anything passed inside parenthesis is consider as function expression.
function(){
alert(2 + 2);
}();
Above is not valid syntax. Because java script syntax parser looks for function name after function keyword since it doesn't find anything it throws an error.
Perhaps the shorter answer would be that
function() { alert( 2 + 2 ); }
is a function literal that defines an (anonymous) function. An additional ()-pair, which is interpreted as an expression, is not expected at toplevel, only literals.
(function() { alert( 2 + 2 ); })();
is in an expression statement that invokes an anonymous function.
They can be used with parameters-arguments like
var x = 3;
var y = 4;
(function(a,b){alert(a + b)})(x,y)
would result as 7
Those extra parenthesis creates extra anonymous functions between global namespace and anonymous function that contains the code. And in Javascript functions declared inside other functions can only access namespace of parent function that contains them. As there is extra object (anonymious function) between global scope and actual code scoping is not retained.
You can also use it like:
! function() { console.log('yeah') }()
or
!! function() { console.log('yeah') }()
! - negation op converts the fn definition to fn expression, therefore, you can invoke it immediately with (). Same as using 0,fn def or void fn def

Categories

Resources