Different ways to define a function in JavaScript.

Manuel Martin Jukisz
4 min readOct 2, 2020

Functions are one of the fundamental building blocks in JavaScript, learning how to really use them will make your life easier.

So lets start by, what is a function?

A function is a sequence of instructions or a “subprogram” that can be invoked by the code that is external (or internal) to that function. In essence, functions “encapsulate” a particular task to later be used.

Functions in JavaScript

Functions in JavaScript are first-class objects, which means that functions can be treated like any other JavaScript object and can be referenced as other variables or passed as arguments to a function.

Functions are similar to JavaScript objects, they can even have properties and other methods. The main difference between a function and other objects is that a function can be invoked (or called).

Every function in JavaScript is a Function object. You can go into the console and try this out:

function typeCheck() {};
typeCheck instanceof Function // Logs True

There are few different ways for a function to be defined in JavaScript, the way a function is defined affects the function behavior.

Let ‘s explore different ways of defining functions.

Function declaration

Lets start by the most common and familiar way to define a function. A function declaration is compose of a name preceded by the mandatory function keyword and followed by an optional list of parameters which are inside the parentheses().

function sum(param1, param2) {
return param1 + param2;
}

All good so farm, now the is two notes about function declaration:

  • A variable that holds the function object is created in the current scope with the same identifier as the function name provided — in our example, sum.
  • The variable is hoisted to the top of the current scope.

To understand hoisting better, let’s look at an example:

console.log(notYetDeclared()); // Logs 'Here!'function notYetDeclared() {
return 'Here';
}

We were able to invoke the function notYetDeclared before we defined it.

Function expression

A function expression is very similar in syntax to a function declaration. There are some difference, like that a function expression doesn’t need a function name.

let sum = function(param1, param2) {
return param1 + param2;
};

Function expressions are a part of another statement. Following our example, the function expression is part of the sum variable assignment.

Unlike function declaration, function expressions are not hoisted.

console.log(notYetDeclared); // Logs 'undefined'let notYetDeclared = function() {
return 'Here';
}

Arrow functions

Arrow functions are an ES6 addition and are meant to be a syntactically compact alternative to function expressions. Arrow functions are defined using a pair of parentheses containing a list of parameters, followed by a fat arrow => and then the function statements with curly braces {}.

let sum = (param1, param2) => {
return param1 + param2;
};

Since one of the main motivations behind the arrow function is syntax compactness, if the only statement in the arrow function is return, we can remove both the curly braces and the return keyword, like so:

let sum = (param1, param2) => param1 + param2;

Also, the parens can be eliminated if we have only one parameter being passed to the arrow function:

let double = param1 => param1 * 2;

Generator function

Generators are an ES6 addition. Generators are a special type of function in the sense that unlike traditional functions, generators produce multiple values on a per-request basis while suspending their execution between these requests.

function* idMaker() {
let index = 0;
while(true)
yield index++;
}let gen = idMaker();console.log(gen.next().value); // Logs 0
console.log(gen.next().value); // Logs 1
console.log(gen.next().value); // Logs 2

You can read about it in more detail here.

Function Constructor

As mentioned earlier, every function in JavaScript is a Function object, so to define a function, we can also directly call the constructor of the Function object.

let sum = new Function('param1', 'param2', 'return param1 + param2');

The arguments are passed as a list of comma-separated strings 'param1', 'param2', ..., 'paramN', and the last argument is the function body passed in as a string.

This method is less efficient than function declaration or function expression.Functions defined using the Function constructor are parsed each time the constructor is called because the function body string needs to be parsed each time, unlike others, which are parsed with the rest of the code.

One use case for defining functions this way is to access the global object in Node or the window object in the browser. These functions are always created in the global scope and do not have access to the current scope.

Conclusion

The choice of which definition type to use is dependent on the situation and what you are trying to achieve. A few general pointers to keep in mind:

  • If you want to leverage function hoisting, use function declarations
  • Arrow functions are well suited for short callback functions and, more importantly, when the desired this is the enclosing function.
  • Avoid using the Function constructor to define functions. If the annoying syntax wasn’t enough to keep you away, it is extremely slow because the function gets parsed each time it’s called.

--

--