Functions are of two types in JavaScript - declarations and expressions.
This is the difference between the two:
- Function declarations are hoisted. This means you can call the function before it appears in the program as declarations in JavaScript are hoisted.
- Function expressions can be invoked immediately. A function declaration cannot. This is because expressions express (or return a value). Function expressions express a function.
An example of a function declaration:
foo("bar");
function foo(bar) {
alert("foo" + bar);
}
The above program will work because foo
is a function declaration.
foo("bar"); // throws an error, foo is undefined - not a function
var foo = function (bar) {
alert("foo" + bar);
};
The above program will not work as foo
is declared as undefined
, hoisted and then later assigned the value of a function expression. Hence it's undefined
when it's called.
An example of a function expression:
(function (bar) {
alert("foo" + bar);
}("bar"));
The above function will be immediately invoked as it's a function expression.
function (bar) {
alert("foo" + bar);
}("bar"); // throws an error, can't call undefined
The above function will not be immediately invoked as it's a function declaration. Remember, declarations do not express (or return a value). So it's like trying to invoke undefined
as a function.
How does a function become an expression?
If a function is used in the context where an expression is expected then it's treated as an expression. Otherwise it's treated as a declaration.
Expressions are expected when:
- You're assigning a value to a variable (i.e.
identifier = expression
). - Inside parentheses (i.e.
( expression )
). - As an operand of an operator (i.e.
operator expression
).
Hence the following are all function expressions:
var foo = function () {};
(function () {});
~function () {};
Everything else is a function declaration. In short if your function is not preceded by anything, it's a declaration.
See this code: https://github.com/aaditmshah/codemirror-repl/blob/master/scripts/index.js#L94
The following function isExpression
is used to test whether some arbitrary JavaScript code is an expression or not:
function isExpression(code) {
if (/^\s*function\s/.test(code)) return false;
try {
Function("return " + code);
return true;
} catch (error) {
return false;
}
}
Hope this clears any doubts in your mind.
In short:
- A function expression expresses or returns a value (in this case a function). Hence it can be immediately invoked, but it can't be called before it appears in the program.
- A function declaration is hoisted. Hence it can be called before it appears in the program. However since it doesn't express any value it can't be immediately invoked.