What the Function?

Understanding the Different Roles of Functions in JavaScript

One of my favorite interview questions for JavaScript developers asks the interviewee to describe some of the different kinds of functions in JavaScript and when they’re useful. This is a good open-ended question, because you’ll get a range of different answers depending on someone’s experience.

I thought I’d take some time to answer this question more fully, both to better my own understanding and to help out anyone who might be interviewing to join my team one day. I’ll focus on what you might call the more “formal” kinds of functions in JavaScript, as well as covering a few other valid answers that aren’t necessarily defined by JavaScript.

The “Formal” Kinds of Functions

JavaScript recognizes three distinct flavors of function: function declarations, function expressions, and anonymous functions.

Function Declarations

If you’ve ever created a function, you’ve probably written a function declaration. They look like this:

function myFunction() { /* ... */ };
function myOtherFunc(param) { /* ... */ };

A function declaration creates a new function in memory. If it has a name, like the two above, it can be referenced within its scope by that name.

The name also identifies the function in context, which is handy for debugging stack traces. Your functions’ names will appear as callers in your stack trace when you get an error report in your console.

One caveat is that functions cannot be declared inside of if block and loops. (Well, they can be in some browsers. But the spec says no.) Named functions declarations are also hoisted to the top of their scope. This means that you can use a function before you declare it:

myFunction(); // => true;
function myFunction() {
return true;
}

Function Expressions

The value of a function declaration is the function itself. Because function declarations have a value, they can be assigned to variables, like this:

var myFunction = function myFunction() { /* ... */ };
var myObject = {
myMethod: function anotherFunction() { /* ... */ }
};

This is called a function expression. You might write a function expression when you’re building a custom object, such as “myMethod” in the example above. We also often use anonymous function expressions as callbacks:

asyncFunction(function(data) { /* ... */ });

We can use function expressions just about anywhere we might use a static value, like a number or a string. You can even return a function expression from another function, like this:

function curryAdd(num) {
var newNum = num + 1;
  return function(otherNum) {
return newNum + otherNum;
};
}

Anonymous Functions

As I mentioned in the previous section, anonymous functions are commonly used in the context of creating callbacks. An anonymous function is simply a function declaration or expression without a name.

You can also assign the value of an anonymous function expression to a variable, allowing you to pass it around and reuse it:

var myAnon = function(data) { /* ... */ };
asyncFunc(myAnon);
anotherAsyncFunc(myAnon);

Anonymous function declarations are another story, though. You can write them, but they won’t do anything on their own. Technically speaking, an anonymous function declaration is an anonymous function expression — function declarations require a name.

// This won't do anything:
function (data) { /* ... */ };

The “Informal” Kinds of Functions

Next, we’ll look at some other patterns that use functions. These are not recognized in JavaScript, and some of these patterns are used in other programming languages.

Methods

Methods are object properties whose value is a function. JavaScript and its many libraries are full of method definitions and calls. Here are some methods you may have used:

// .getElementById()
document.getElementById('my_id');
// .addClass()
$('#my_id').addClass('my-class');

The important thing to remember about methods is that they only exist in a particular context. We can’t call the above methods from just any object. The getElementById method exists on the built-in document object. The addClass method exists on the jQuery object.

In software engineering, we refer to a group of related functionality (and data, sometimes) as an object. Methods, then, are functions that have been grouped together intentionally by a developer.

Immediately Invoked Function Expressions

Immediately invoked function expressions, or IIFEs, are function expressions that are called as soon as they’re defined. This pattern is often used to create the concept of encapsulation in JavaScript.

(function() { /* ... */ })();

First, we have an anonymous function declaration wrapped in parentheses. This first set of parentheses evaluates and contains the function.

The second set invokes, or calls, that function expression. Everything inside of this function is contained within its own private scope, meaning it cannot affect anything outside of the function.

Anything included in the second set of parentheses will be passed to the function as arguments. You might have seen the following pattern:

(function($) {
/* ... */
})(jQuery);

The goal of this is to make sure that the $ variable maps to the global jQuery object inside of our scope, even if it has been overwritten in the outer/global scope. This concept is called a closure.

Closures

When we create scope with a function, we create a closure. Closures allow us to write our programs in a way that does not affect anything but what we wrote. It ensures that when we name a variable a certain way, nothing outside of our program can affect it.

You’ll often see JavaScript programs written entirely inside of an IIFE. This is one of the most common uses of closures in JavaScript:

var myFunction = (function() {
// can’t access from outside
var privateValue = ‘hello world’;
  return function() {
return privateValue;
};
})();
console.log(privateValue); // => undefined
console.log(myFunction()); // => ‘hello world’

In this example, the value of myFunction is the function returned inside of the IIFE. myFunction has access to privateValue, but we cannot access that variable from outside of myFunction.

Factory Functions

Factory functions are functions that return objects. This is a common way to create multiple instances of objects. Here’s a simple example:

var myFactory = (function() {
return {
myProp: true,
myMethod: function() { /* ... */ }
};
})();
console.log(myFactory.myProp); // => true
myFactory.myMethod(); // will execute

Factory functions provide an alternative to prototypal inheritance in object-oriented JavaScript. Here’s an example comparing the two methods:

// Prototypal inheritance
function MyFunction() {
this.color = 'blue';
this.shape = 'square';
}
var func = new MyFunction();
console.log(func.color); // => 'blue'
console.log(func.shape); // => 'square'
// Factory function
function MyFunction() {
var color = 'green';
var shape = 'circle';
  return {
color: color,
shape: shape
};
}
var func = MyFunction();
console.log(func.color); // => 'green'
console.log(func.shape); // => 'circle'

What else?

This may not be an exhaustive list, so if you can think of anything I missed (or anything I got wrong) let me know in a response!