Defining JavaScript Functions


There are many ways to create functions in JavaScript; some styles are quite popular e.g. the function declaration and function expression while others are not.

//function samples
function declaration () {};
var funcExpression = function () {};
var namedFuncExpression = function named() {};
var fnConstructor = new Function ();

All approaches create a Function object however there are a couple of differences under the hood. Lets take a peek…

1. Function Declaration

The function declaration pattern is one of the most common patterns.


function fn () {
    //function body
}

Once a function is defined using the declaration format; it can be used anywhere in the enclosing scope even before the function body. Confusing? It’s all about hoisting.

2. Function Expressions

Functions are first class objects in JavaScript, thus it is possible to have expressions that evaluate to function values; such expressions are appropriately termed function expressions.

Creating a function expression is easy: just declare a function where the parser expects an expression and it automatically becomes a function expression. This includes assignments to variables and/or object properties, placing functions between parentheses (the grouping operator can only contain expressions),or after a unary operator (e.g. !, +, – etc).

//anonymous function expressions
var fnExpr = function () {};

(function fnExpr2() {} );

!function fnExpr3() {}

Function expressions can be named or anonymous; named function expressions (NFE) expose a function name that is available inside the function body but not outside it. See the snippet below:

var namedFuncExpression = function named() {
    return named.name;
};

named();
//ReferenceError, named is not defined

namedFuncExpression();
//returns "named"

NFEs help to make debugging nicer (we all know how frustrating it is to keep seeing ‘anonymous’ functions in the debugger). It might also come in handy when you need to retrieve a function name by calling toString() or make recursive functions (although the variable name will also serve the same purpose).

Function expressions are essential to achieve functional programming concepts like currying and partial application in JavaScript.

3. Function Constructor

The last way is to use the function constructor, this constructs a function object and returns it.

There are a few things to note while using this approach: created functions can only access variables in the global scope or in their own scope and it is no possible to create closures. Moreover, the use of the function constructor is slower since the function body has to be parsed every time it is called. And there are potential risks from malicious agents.

var add = new Function('a','b', 'return a + b');

add(1,2);
//3

var glbFoo = "global";
function scope() {
  var scpFoo = "scoped";,
   scop=Function('console.log(typeof scpFoo)'),
   glob=Function('console.log(typeof glbFoo)');

   scop();
   glob();
}

scope();
//logs undefined
//logs string

The parameters to the function are passed in first and then the function body (as a string) is passed in as the last parameter and viola! the function object is returned. The new keyword is optional; it still works without the new.

4. Function expression vs Function declaration

Function declarations and their bodies get hoisted to the top of the scope (no matter where they appear – top, bottom or middle) and are thus available through the scope. However for function expressions, the variable declaration is hoisted while the assignment to the function body only happens at runtime. See the example below:

declared();
//logs declared
function declared () {
    console.log('declared');
}

expressed();
//logs TypeError: undefined is not a function

var expressed = function () {
    console.log('expressed ');
}
expressed();
//logs expressed

5. Spot the difference? Identifying function expressions and declarations in code

Differentiating between function expressions and declarations can be tricky. According to the ECMAscript specification, function declarations must have an identifier. If functions without identifiers are unequivocally function expressions, how do we distinguish between a function declaration and a named function expression?

Function declarations are only allowed as sourceElements of scripts or functions. They cannot appear in nested blocks because blocks are  only allowed to contain statements and not sourceElements. Expressions on the other hand are expressions… :)

//source element examples
var a = 0;
function b () {};
if (false) {
    //nested, not source element
    var c = 0;
    function d () {};
}

//function declaration
function foo() {
    //another declaration
    function bar() {};

    if(true) {
        //function expression because
        //it is not a source element
        function baz() {};
    }

    //function expression
    //expressions expected after unary operator
    !function bng () {};
};

6. Finally…

Still reading? Here are some more examples of queer ways to create functions. Don’t do this at home/work/live/staging/etc.

var f = function (str) {
    alert(str);
};
eval('f("eval")');
//alerts eval

setTimeout('f("timeout")',1000);
//alerts timeout after a sec
};

Remember, don’t do this on live servers…

Did you enjoy this post? Here are a couple more interesting posts:

1. The JavaScript Function
2. Three Important JavaScript Concepts
3. A peek into JavaScript’s Array.prototype.map and jQuery.map

Update

Brilliant explanation of the difference between function and Function by Peter van der Zee:

“The `Function` is a global object and a function value, which generates a new function when called. You create new local variables named `Function` but not with `function` “

0 Comments

·

Leave a Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.