Methods for defining functions in JavaScript
Tags: javascript
Published: 2019-09-25 13:44:03

---
title: Methods for defining functions in JavaScript
published: true
tags: javascript
canonical_url: https://blog.logrocket.com/defining-functions-in-javascript/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/yuja3g61mghcf7s7y7ta.jpeg
---
**Written by [Yash Agrawal](https://blog.logrocket.com/author/yashagrawal/)**✏️

Generally, 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.

Functions are one of the fundamental building blocks in JavaScript, and _really_ understanding functions can help tackle some of [JavaScript’s oddities](https://blog.logrocket.com/common-javascript-gotchas-638bdea2a224/).

## Functions in JavaScript

It is important to note that functions in JavaScript are first-class objects. This basically means that functions in JavaScript can be treated like any other JavaScript object and can be referenced as other variables or passed as arguments to a function.

Functions can even have properties and other methods, just like any other JavaScript object. The key 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:

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

The `Function` object has a few specific methods and properties, like `apply`, `call`, `bind`, `isGenerator`, etc., that are not available with other objects.

There are a few different ways in which a function can be defined in JavaScript, and the way it is defined affects function behavior. Let’s explore each way one by one.

### Function declaration

This might be the most familiar way to define a function. A function declaration consists of a name preceded by the mandatory `function` keyword and followed by an optional list of parameters inside a required pair of parentheses `()`.

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

Two main things to note about this form of defining a function are:

- 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. You can [read more on that here](https://www.yagrawal.com/hoisting-in-javascript).

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

```jsx
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. The major difference is that a function expression does not need a function name.

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

Function expressions are a part of another statement. In the example above, the function expression is part of the `sum` variable assignment.

Unlike function declaration, function expressions are _not_ hoisted.

```jsx
console.log(notYetDeclared); // Logs 'undefined'

let notYetDeclared = function() {
  return 'Here';
}
```

An interesting use case for function expressions is their ability to create IIFEs, or Immediately Invoked Function Expressions. There are instances in which we might want to define a function and invoke it right after the definition, but never again.

Sure, it can be done with function declaration, but to make it more readable, and to make sure that our program doesn’t accidentally access it, we use an IIFE. Consider this example:

```jsx
function callImmediately(foo) {
  console.log(foo);
}

callImmediately('foo'); // Logs 'foo'
```

We create a function called `callImmediately`, which takes an argument and logs it, and then we immediately call it. The same result can be achieved by doing this:

```jsx
(function(foo) {
  console.log(foo);
})('foo'); // Logs 'foo'
```

The key difference is that in the first case, the function declaration pollutes the global namespace, and the named function `callImmediately` hangs around long after it is required. The IIFE is anonymous and hence cannot be called in the future.

### Arrow functions

[Arrow functions](https://dev.to/bnevilleoneill/anomalies-in-javascript-arrow-functions-2afh) 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 `{}`.

```jsx
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:

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

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

```jsx
let double = param1 => param1 * 2;
```

Some important things to note in this form of function definition are:

- An arrow function does not have its own `this`, and it uses the `this` value of the enclosing lexical scope. You can read more about `this` [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this).

```jsx
let foo = {
    id: 10,
    logIdArrow: () => { console.log(this.id) },
    logIdExpression: function() {
      console.log(this.id);
    }
  }
  
  foo.logIdArrow(); // Logs 'undefined'
  foo.logIdExpression(); // Logs '10'
```

In the above example, we have an arrow function and a function expression that logs `foo.id` using `this`.

- An arrow function does not have the `prototype` property.

```jsx
let foo = () => {};
console.log(foo.prototype); // Logs 'undefined'
```

- The `arguments` object is not available in an arrow function. You can read more about the `arguments` object [here](https://www.yagrawal.com/parameters-&-arguments-in-javascript).

### `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.

```jsx
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.

Performance-wise, this way of defining a function 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.

### 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.

```jsx
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
```

The `function*` and `yield` keywords are unique to a generator. Generators are defined by adding an `*` at the end of a function keyword. This enables us to use the `yield` keyword within the body of the generator to produce values on request.

You can read about it in more detail [here](https://www.yagrawal.com/generators-in-javascript).

## 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 — for example, in situations where you want to move the function implementation details to the bottom and just the abstracted flow on top for clarity.
- 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.

* * *
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/defining-functions-in-javascript/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [Methods for defining functions in JavaScript](https://blog.logrocket.com/defining-functions-in-javascript/) appeared first on [LogRocket Blog](https://blog.logrocket.com).