function-expression

Immediately Invoked Function Expression in CoffeeScript

CoffeeScript only has function expression, there are no named functions nor function declaration, as almost everything in CoffeeScript is expression.

Anonymous function can be written as just a dash plus an arrow:

1
->

This will be compiled to JavaScript:

1
(function () {});

This anonymous function can be invoked immediately:

1
2
// (->)()
(function () {})();

The immediately invoked function expression (IIFE) syntax is different from the preferred format in JavaScript. But this is more likely due to the syntax and compilation of CoffeeScript.

Here is one useful example to show the syntax:

1
2
3
4
5
6
// (square = (n) -> return n * n)()
var square;
(square = function(n) {
return n * n;
})();

And a few more without compiled Javascript:

1
2
3
(->)()
(square = (n) -> return n * n)()
console.log (square = (n) -> return n * n)(10) # 100

Immediately Invoked Function Expression

What’s difference between:

1
2
(function(){}());
(function(){})();

This is function declaration:

1
function foo(){}

The identifier of the function declaration is required.

This is function expression:

1
var foo = function(){};

The right hand side of the assignment must be an expression. And function identifier is optional. Check the previous article about the difference between function declaration and function expression.

Now, come in the grouping operator, which return the result of evaluating an expression:

1
(function(){});

If we do it with named function:

1
2
function foo(){}
(foo);

or

1
(function foo(){});

But we haven’t done anything here, in another word, we haven’t invoked the function. We merely evaluate the function in three occasions. Function is object in JavaScript, when you’re evaluating an object, the result is still an object:

1
2
3
4
5
console.log(function foo(){}); // [Function: foo]
console.log(function (){}); // [Function]
function bar(){}
console.log(bar); // [Function: bar]
console.log({}); // {}

Now, let’s apply function invocation, and do it the traditional way:

1
foo();

The function has been invoked, and it will return the result of the function.

Replace the identifier with function declaration:

1
function foo(){}();

However, this does not work. Because interpreter treats it as a function declaration, and ( will become an unexpected token. Function declaration cannot be invoked immediately. So, we need to make it an expression, by using the grouping operator:

1
(function foo(){})();

The function identifier is no longer necessary:

1
(function(){})();

Since grouping operator return the result of the expression, we can just drop it:

1
function(){}();

But this statement becomes a function declaration again, so we need to place the grouping operator around it:

1
(function(){}());

Okay, but what’s difference between:

1
2
(function(){}());
(function(){})();

There is no difference, they are both function expressions being invoked immediately. Function invocation can only be done via function expression. But first one is more align with foo(), the traditional way. According to the Code Convention for JavaScript Programming Language by Douglas Crockford:

When a function is to be invoked immediately, the entire invocation expression should be wrapped in parens so that it is clear that the value being produced is the result of the function and not the function itself.

The invocation expression is function(){}(), and wrap it around parenthesis becomes (function(){}());.

Therefore, this first method is more traditional and preferred.

Function Declaration and Function Expression

In JavaScript, what is function declaration?

function square(n) { return n * n; }

Here we declare a function and name it “square”. But what is function expression?

var square = function (n) { return n * n; };

When you start a statement with keyword function, then the statement is function declaration, everything else is function expression.

Function expression can either be named or anonymous. The above is anonymous function, and here is a named one:

var square = function square(n) { return n * n; };

There is a variable square and function name square, but they are not the same. The scopes are different. The function name square of the function expression can be only used inside the function, mainly for debugging purpose. Accessing from outside the function, will throw ReferenceError:

var foo = function bar() {};
bar(); // ReferenceError: bar is not defined

We can also use property ‘name’ to differentiate a named vs. an anonymous function:

console.log(square.name); // empty string for an anonymous function

However, you cannot create an anonymous function declaration, for a very obvious reason:

function (n) { return n * n; } // SyntaxError: Unexpected token (

Another difference between function declaration and function expression is hoisting:

square(10); // 100
function square(n) { return n * n; }

Function defined by declaration is hoisted, but not for function expression:

square(10); // TypeError: undefined is not a function
var square = function (n) { return n * n; }

The variable declaration is hoisted, but not for the definition. Therefore, result in TypeError. However, for best practice, functions should be defined before being used.

In conclusion:

  • Function declaration must start with keyword function in the beginning of the statement. Everything else is function expression.
  • Function expression can be anonymous and named, but function declaration can only be named.
  • Function declaration is hoisted, but not function expression.

This function declaration happens inside a unreachable block.

square(10); // 100
if (false) {
  function square(n) { return n * n; }
}

There is no block scope in JavaScript. Spaces in the beginning of keyword function do not count. This is still a valid function declaration.

A simple way to turn function declaration into function expression is by wrapping around parentheses:

(function square(n) { return n * n; });

We are applying the grouping operator () here, which evaluates the function expression.

Another way:

foo(err, function(){});

Just think about , as ().

Other good reads: