BlogsDope image BlogsDope

Different Ways to Define a Function in JavaScript

July 13, 2020 JAVASCRIPT FUNCTION 469

A function is a block of code that is defined once and used multiple times. It makes your code reusable, readable, and maintainable, etc. There are several ways of declaring functions in JavaScript. Let’s go through them one by one.

The Function Declaration


This is the most common and standard way of defining a function. It contains the keyword function followed by a function name, parameters in parenthesis, and the function body inside the curly brackets. By default, the function returns undefined. However, you can use a return statement. Let’s see the syntax.

function functionName (param1, param2, , paramN){
  //statements
  }

The function can have zero or more parameters depending upon your requirement. Let’s create a function that takes two arguments and calculates the sum of their squares.

<script type="text/javascript">
  function sumOfSquare(num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  }

  result = sumOfSquare(4, 3);
  console.log(result);
</script>

Output

25

The name of the function is sumOfSquare. It takes two arguments, num1 and num2, and returns their sum of squares.

Functions defined using this way are hoisted. Hoisting is a concept in JavaScript in which the JavaScript interpreter moves function and variable declarations to the top of their scope at the runtime. That means they can be accessed anywhere in the code, i.e., before declaration too. Let’s see.

<script type="text/javascript">
  result = sumOfSquare(4, 3);
  console.log(result);

  function sumOfSquare(num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  }
</script>

Output

25

The function was invoked before its declaration, and as you can see, we got an output and not an error.

The Function Expression


This is another way of defining a function. It is almost similar to the above method expect you assign a function to a variable, and the function name is optional. It does not start with the function keyword. There are two types of function expressions. If you provide a name to the function, it is known as a named function expression. Otherwise, it is known as an anonymous function expression.

<script type="text/javascript">
  const sumOfSquare = function (num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  };
  result = sumOfSquare(2, 3);
  console.log(result);
</script>

Output

13

In the above example, we have not provided any name to the function. Therefore, it is an anonymous function. We have assigned it to the const sumOfSquare.

Let’s now see an example of the named function expression.

<script type="text/javascript">
  const sumOfSquare = function sOfSq(num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  };
  result = sumOfSquare(2, 3);
  console.log(result);
</script>

Output

13

Note that always invoke the function with the variable/constant it is assigned. Using the function name will throw an error. However, if it calls itself, then you can use both.

<script type="text/javascript">
  const sumOfSquare = function sOfSq(num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  };
  result = sOfSq(2, 3);
  console.log(result);
</script>

Output

function.html:15 Uncaught ReferenceError: sOfSq is not defined
    at function.html:15

One main difference between the function declaration and the function expression is that the functions declared using the expression are not hoisted, i.e., you can’t access them before the declaration. Let’s see.

<script type="text/javascript">
  result = sumOfSquare(2, 3);
  console.log(result);
  const sumOfSquare = function (num1, num2) {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  };
</script>

Output

function.html:10 Uncaught ReferenceError: Cannot access 'sumOfSquare' before initialization
    at function.html:10

Self-Invoking Function Expression


A self-invoking function expression executes automatically without being invoked. To do so, wrap it with parenthesis and add () after it. If the function contains arguments, pass them inside (). Let’s see an example.

<script type="text/javascript">
  (function () {
    console.log("Hi, I am a self-invoking function!");
  })();
</script>

Output

Hi, I am a self-invoking function!

It is also known as Immediately-Invoked Function Expression (IIFE).

The Generator Function Declaration


Generator function


The functions that we have studied so far execute all of the statements in one go. In other words, they can’t be stopped midway and rerun from the same point. Unlike regular functions, generator functions can do so. To declare it, add an asterisk after the function keyword. When we invoke a generator function, it returns an iterator object. Note that it does not start executing at this point. The iterator object contains a next() method. When we call it, the function executes until it encounters a yield expression. A yield expression represents the value to be returned from the iterator. The next() method contains two properties. The next().value represents the returned value, and the next().done represents whether the generator has finished its entire execution. The next().done returns true after the last yield expression. If you use a return statement at any point, then the next().done will return true, and the function won’t execute more.

Let’s take an example and see how this works.

function* generator() {
  i = 1;
  console.log("First execution point");
  yield i;
  i = i + 1;
  console.log("second execution point");
  yield i;
  i = i + 1;
  console.log("Last execution point");
  yield i;
}

var iterator = generator();
next = iterator.next();
while (!next.done) {
  console.log("Output: " + next.value);
  next = iterator.next();
}

Output

First execution point
Output: 1
second execution point
Output: 2
Last execution point
Output: 3

In the above example, we have created a generator() function that yields three integers. The iterator object returned by the function is stored in the iterator variable, and the object returned by the next() method is stored in the next variable. The condition inside the while loop checks whether the generator() has finished its execution or not. If it hasn’t, then it displays the output value and resumes the execution.

Consider the following example where we add a return statement in the generator() function, and it stops its execution at this point.

function* generator() {
  i = 1;
  console.log("First execution point");
  yield i;
  i = i + 1;
  console.log("second execution point");
  return i;
  i = i + 1;
  console.log("Last execution point");
  yield i;
}

var iterator = generator();
next = iterator.next();
while (!next.done) {
  console.log("Output: " + next.value);
  next = iterator.next();
}

Output

First execution point
Output: 1
second execution point

In the second run, it encounters a return statement, and the value of the done property becomes true. That's why the while loop exits.

For more details, check the function* statement.

Just like the regular function, we can create the generator functions using the generator function declaration. In the above examples, we used this way of defining them.

The Generator Function Expression


This is similar to the regular function expression, except the function keyword is followed by an asterisk.

Arrow Function Expression


An arrow function expression is a compact way of creating functions. It got introduced in ES6 (ECMAScript 2015). Here is how you define them.

(param1,param2,  paramN) => {
  //statements
  s}

As you can observe, the arrow function expressions do not require the function keyword, and they are anonymous. If the function contains a single parameter, then you can ignore the parenthesis. Moreover, if it has only one statement, then you can ignore the curly brackets and the return keyword as well. Let’s see.

<script type="text/javascript">
  // multiple statements and parameters
  const sumOfSquare = (num1, num2) => {
    num1 = num1 * num1;
    num2 = num2 * num2;
    return num1 + num2;
  };
  console.log(sumOfSquare(3, 4));
  //single parameter and statement
  const square = (num1) => num1 * num1;
  console.log(square(4));
</script>

Output

25
16

The arrow function expression does not bind its own this value. However, it inherits the value from the parent scope. This is known as lexical binding. Moreover, it is not hoisted as well. For more information, visit the arrow function expression.

The Function Constructor


As we know that JavaScript functions are objects of type Function, therefore we can create them by calling the constructor Function() using the new operator. The arguments to the constructor are the names of the parameters followed by a string containing the function body. Let’s see an example.

const product = new Function("a", "b", "return a*b");
console.log(product(3, 4));

Output

12

Avoid using this as it prevents the JS engine to perform some optimizations, and it can cause problems too. You can't call the function before declaration as it is not hoisted.

As you have seen, there are a lot of ways to define a function. Each has its advantages and disadvantages. It depends upon the situation at hand to decide which one to use. For example, use generator functions for async activities. When the function needs to be called only once, use IIFE. Arrow function expressions are preferred when the function body is short, i.e., it contains a one-line statement, and the value of this is to be bound to the parent scope.


Liked the post?
A computer science student having interest in web development. Well versed in Object Oriented Concepts, and its implementation in various projects. Strong grasp of various data structures and algorithms. Excellent problem solving skills.
Editor's Picks
0 COMMENT

Please login to view or add comment(s).