Take notes from this post Immediately-Invoked Function Expression(IIFE)
Function declaration & function expression
Now, whether you define a function likefunction foo(){}orvar foo = function(){}, what you end up with is an identifier for a function, that you can invoke by putting parens (parentheses, ()) after it, likefoo().1
2
3
4
5
6
7
8
9
10// Because a function defined like so can be invoked by putting () after
// the function name, like foo(), and because foo is just a reference to
// the function expression `function() { /* code */ }`...
var foo = function(){ /* code */ }
// ...doesn't it stand to reason that the function expression itself can
// be invoked, just by putting () after it?
function(){ /* code */ }(); // SyntaxError: Unexpected token (As you can see, there’s a catch. 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. If you don’t explicitly tell the parser to expect an expression, it sees what it thinks to be a function declaration without a name and throws a Sounters the function keyword in the global scope or inside a funct)
functions, parens, and SyntaxErrors
Interestingly enough, if you were to specify a name for that function and put parens immediately after it, the parser would also throw a SyntaxError, but for a different reason. 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).1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// While this function declaration is now syntactically valid, it's still
// a statement, and the following set of parens is invalid because the
// grouping operator needs to contain an expression.
function foo(){ /* code */ }(); // SyntaxError: Unexpected token )
// Now, if you put an expression in the parens, no exception is thrown...
// but the function isn't executed either, because this:
function foo(){ /* code */ }( 1 );
// Is really just equivalent to this, a function declaration followed by a
// completely unrelated expression:
function foo(){ /* code */ }
( 1 );The solution: Immediately-Invoked Function Expression (IIFE)
Fortunately, the SyntaxError ‘fix’ is simple. The most widely accepted way to tell the parser to expect a function expression is just to wrap it in parens, because in JavaScript, parens can’t contain statements. At this point, when the parser encounters thefunctionkeyword, it knows to parse it as a function expression and not a function declaration.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Either of the following two patterns can be used to immediately invoke
// a function expression, utilizing the function's execution context to
// create "privacy."
(function(){ /* code */ }()); // Crockford recommends this one
(function(){ /* code */ })(); // But this one works just as well
// Because the point of the parens or coercing operators is to disambiguate
// between function expressions and function declarations, they can be
// omitted when the parser already expects an expression (but please see the
// "important note" below).
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();
// If you don't care about the return value, or the possibility of making
// your code slightly harder to read, you can save a byte by just prefixing
// the function with a unary operator.
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
// Here's another variation, from @kuvos - I'm not sure of the performance
// implications, if any, of using the `new` keyword, but it works.
// http://twitter.com/kuvos/status/18209252090847232
new function(){ /* code */ }
new function(){ /* code */ }() // Only need parens if passing argumentsFirst class
something is first-class if it:
- can be stored in variables and data structures
- can be passed as a parameter to a subroutine
- can be returned as the result of a subroutine
- can be constructed at runtime
- has intrinsic identity (independent of any given name)
Closure example1
2
3
4
5
6
7function Person(name) {
return [function(newName) {
name = newName;
}, function() {
return name;
}];
}
- Closure
The important thing to realise is that a closure actually remembers its environment rather than its free variables, so if you define a new variable in the environment of the closure after the closure’s definition, it will be accessible inside the closure.