Every Possible Way to Define a Javascript Function

One small thing that confused me as I was learning JavaScript was the many different kinds of ways to define a JavaScript function. I could never seem to find one place that showed all of them, and explained why you might use each one.

That is the aim of this post. So without further ado, here are ALL the ways to define a JavaScript function.

Function Declarations:

Type Example Explanation
Named Function Declaration
function sum(num1,num2) {
  return num1 + num2;
}
The "classic" declaration, which works well for simple uses. Functions declared like this are "hoisted", meaning, the JavaScript engine reads all these declarations first before executing any of the rest of the code. The declaration statement stands alone, and cannot be combined with other expressions. Also, notice that this declaration does not need to be followed with a semicolon.

Function Expressions:

Function expressions are very flexible, and can used in many contexts. This list aims to demonstrate that flexibility, and show use-cases for each example. Also: here’s a great article on the differences between function declarations and expressions.

Type Example Explanation
Variable Assignment
// Named
var sum = function add(num1,num2) {
  return num1 + num2;
};

// Anonymous
var sum = function(num1, num2) {
  return num1 + num2;
};

This is functionally equivalent to the Function Declaration above, except this variation is NOT hoisted. The name of our function (add) cannot be called directly (see below), but it can come in handy when debugging:

sum(1,1);
// returns 2

add(1,1);
// "add is not defined"
Immediately invoked
// Named
(function sum(num1, num2) {
  return num1 + num2;
}(1, 2));

// Anonymous
(function(num1, num2) {
  return num1 + num2;
}(1, 2));

This function is immediately invoked, meaning that it is defined and called at the same time. The function's name is only available within its execution scope (defined by the parentheses), so it cannot be called later in the program.

sum(1,1);
// "sum is not defined"

Immediately invoked functions can be used to encapsulate a program, preventing it from polluting the global namespace (here's a simple example of that).

Assigned and Invoked
// Named
var sum = function add(num1, num2) {
  return num1 + num2;
}(1, 2);

// Anonymous
var sum = function(num1, num2) {
  return num1 + num2;
}(1, 2);
This is a combination of the variable assignment expression and the immediately invoked function (both demonstrated above). One neat application for the named variety of this is to make recursive functions more readable, by substituting arguments.callee with your function name.
Passed as Argument
// Named
setTimeout(function add() {
  alert(1 + 2);
}, 500);

// Anonymous
setTimeout(function() {
  alert(1 + 2);
}, 500);

In this example, the setTimeout method takes two arguments: a callback function and a time interval. Like this: setTimeout(callback, interval)

While we could define the callback in a variable and pass it in, we can also use define it inline with a function expression. This function-expression-as-argument is a common pattern for defining callbacks.

Returned (closure)
// Named
function counter() {
    var count = 0;
    return function c() {
        alert(count++);
    }
}

// Anonymous
function counter() {
    var count = 0;
    return function() {
        alert(count++);
    }
}

Functions can be returned from other functions. This lets us do clever things like the following (picking up from the example):

var bob = {}, rob = {};
bob.count = counter();
rob.count = counter();
bob.count(); // alerts "0"
bob.count(); // alerts "1"
rob.count(); // alerts "0"
rob.count(); // alerts "1"

Each person can increment their own count variable despite the fact that it originated outside the scope of the count() function. This is called a closure. Here's some more information on JavaScript closures, if you're curious.

Method Definition
// Named
var obj1 = {
  sum: function add(num1, num2) {
    return num1 + num2
  }
};

// Anonymous
var obj2 = {
  sum: function(num1, num2) {
    return num1 + num2
  }
};

By assigning functions (either named or unnamed) to properties of objects, we define methods on those objects. This can be done on both object literals and classes. This is used in object-oriented programming, and is a practical way to namespace our functions and keep them out of the global scope.

Here's how we would call the methods defined in the examples:

obj1.sum(1, 2);  // returns 3
obj2.sum(1, 2);  // returns 3
Method Definition Shorthand
// Named
var obj = {
  sum(num1, num2) {
    return num1 + num2
  }
};

This shorthand version of the method definition above was introduced in ES2015. It's functionally equivalent to this longer definition:

var obj = {
  sum: function sum(num1, num2) {
    return num1 + num2
  }
};

Thus, we can call method like this:

obj.sum(1, 2);  // returns 3

There is no anonymous version of this definition. When using this shorthand, the defined function assumes the same name as the method.

Arrow Functions
// Named
var sum = (num1, num2) => {
  return num1 + num2
};

// Anonymous
(num1, num2) => {
  return num1 + num2
};

// Anonymous (implicit return)
(num1, num2) => num1 + num2;

Arrow (or "fat-arrow") functions are a shorthand definition that was introduced as part of the ES2015 specification. This example:

var sum = (num1, num2) => {
  return num1 + num2
};

…is functionally equivalent to:

var sum = function sum(num1, num2) {
  return num1 + num2;
};

Arrow functions are anonymous by default, but when assigned to a variable, they assume the variable name.

Arrow functions are function expressions, and as such, they are usable in all the contexts shown above (variable assignment, passed as an argument, etc.). There are several syntax variations—here's a good blog post that describes them all.

Function Constructor

Type Example Explanation
Function Constructor
var sum = new Function(
  'num1', 'num2', 'return num1 + num2'
);
Defining functions with the Function constructor is less performant than the other methods, so I wouldn't recommend this option. However, it is useful in demonstrating that in JavaScript, functions are "just objects."
Constructor w/apply()
var args = ['num1', 'num2', 'return num1 + num2'];

var sum = Function.apply(this, args);
This uses the apply() method to call the constructor of the Function object and create a function. The function can then be run with sum(1,2);. Hard to think of a practical application for this one, but it could be used in rare cases.
Immediately Invoked Constructor w/apply()
var args = ['num1', 'num2', 'return num1 + num2'];

Function.apply(this, args)
        .apply(this, [1, 2]);
This uses the apply() method with the constructor of the Function object to immediately invoke the function we defined. Again, it's hard to think of a practical application for this one, but hey, it works as expected.

Conclusion

I think that’s all of them, but if you know of any others that I’m not aware of, (or have other suggestions to make), let me know in the comments below.

If you want to see patterns and techniques for declaring functions using the methods I described above, check out Addy Osmani’s book, “JavaScript Design Patterns”. It is Creative Common licensed, published online, and freely available to read.


Also, a big thanks to Nicholas Zakas’ book “Professional JavaScript for Web Developers”, which brought a lot of this together for me.

Update 1:

Based on feedback in the comments, I reorganized the table in order to more accurately classify the function declarations and expressions. I also tweaked the examples to (hopefully) be a bit less confusing.

Comments