Functions in JavaScript can be called in different ways. At first glance, that may seem like a crazy statement. How can there be more than one way to call a function? Don’t we just call it?

Well, dear reader, as we shall discuss in this post, there are 4 ways to call a function in JavaScript. Your particular scenario will determine which one to use. Additionally, each method will dictate the value of “this“, also known as the context, within the function.

A point to keep in mind

Whenever a function is called in JavaScript, regardless of how it is called, two implicit arguments are passed to it. Those 2 implicit arguments are this, the context in which the function will execute and the arguments parameter. The arguments parameter is an array-like structure containing any passed arguments. Its “array-like” but it is not an array.

Now, without further ado, let’s introduce the four ways in which a function can be called.

JavaScript functions can be called:

  1. As a function
  2. As a method
  3. As a constructor
  4. via call and apply

Let’s look at each one.

Calling a function as a function

Since the creation of the language, this is probably the way most functions have been called: as a function. If you’ve ever placed a snippet of JavaScript on a web page and called it from a button click, you have called a JavaScript function as a function. Let’s look at a code sample.

<button onclick="sayHello()">say hello</button>
  <script>
    function sayHello() {
      console.log(this);
      console.log(arguments);
      console.log('hello');
    }
  </script>

In this simple code example, we have a button that when clicked, calls the sayHello() function. Within the function, we log the value of this followed bu the value of arguments. Then we say hello. Let’s see what we get in the console when we click the button.

the output from our simple sayHello function

As you can see, the value of this is the Window object. That is the context in which our nifty little function is executing. You do have the option to force the context of this to be undefined in this case. To do so, you simply add the ‘use strict’; directive to your code.

<button onclick="sayHello()">say hello</button>
  <script>
    'use strict';  //force the context to be undefined
    function sayHello() {
      console.log(this);
      console.log(arguments);
      console.log('hello');
    }
  </script>

The arguments parameter in this instance does not have any values since no parameters were passed to the function.

Calling a function as a method

In order to call a function as a method, it must be defined as a property on an object. Let’s look at some code.

  <button onclick="greeter.sayHello()">say hello</button>
  <script>
    greeter = {
      sayHello: function () {
        console.log(this);
        console.log(arguments);
        console.log('hello');
      }
    }

Here you can see that we have wrapped the sayHello() function inside an object called greeter thus making it a property on that object. We then update our onclick handler to call it using the object dot syntax: greeter.sayHello()

When we call the function in this way, here is what we get in the console:

calling sayHello as a method

Here we see that the context of the this argument points to the greeter object. This makes more sense than the global window object. As expected, we still have access to the arguments parameter as well.

Calling a function as a constructor

Before we look at the code for calling a function as a constructor, let’s take a moment and consider the purpose of a constructor. A constructor is meant to set up some initial state within an object. To construct it. That being the case, this is a more specialized case of how to call a function. We are calling this function with the intent of creating something new and getting it back. Let’s look at a code sample.

  <input type="text" id="name"></input>
  <button onclick="sayHello()">say hello</button>
  <script>

    function Greeter(name) {
      console.info('begin constructor');
      console.log(this);
      console.log(arguments);
      this.name = name;
      console.info('end constructor')
    }


    function sayHello() {
      var name = document.getElementById('name').value;
      var grtr = new Greeter(name);
      console.log('hello ' + grtr.name);
    }
  </script>

In this example, we have added an input text box so that the user can enter their name. It’s not really a proper greeting without a name. Once again, when our button is clicked we call the sayHello() function. In our sayHello function, we grab the value in the text box and create a new instance of the Greeter object by calling new Greeter().

The new keyword and the capital G make it clear that this function is being called as a constructor. When a function is called in this way, this is set to the newly created object. We then add a name property to the newly created object and set its value to the parameter that was passed to the constructor. The newly created object is passed back to the calling code and saved in the grtr variable. Finally, in the call to console.log, we access the name property that we just set on the Greeter object.

Calling a function via call and apply

One thing to always keep in mind when working with functions in JavaScript is that they are first-class objects. That means that a function can have its own properties and its own methods. Yes, you read that correctly. A function can have its own methods. The call and apply methods are two of those methods. The call and apply methods allow you to specify the context in which the function will execute. They allow you to set the this value. Let’s take a look at a code example.

  <button onclick="go()">GO</button>
  <script>
    var people = [];
    var name = 'alex';

    function Person(idx) {
      idx % 2 === 0 ? 
        this.name = 'alex ' + idx : 
        this.name = 'bob ' + idx;
    }

    function printName() {
      console.log(this.name);
    }

    function go() {
      //call printName to print the name variable defined on the window object
      printName();

      //populate the people array with a couple of people
      for (let idx = 0; idx < 5; idx++) {
        people.push(new Person(idx));
      }

      // lets call the printName for each object that we just created 
      // seting this dynamically
      people.forEach(p => {
        printName.call(p);
      });
      // printName.call(valueOfThis, 1, 2, 3);
      // printName.apply(valueOfThis, [1, 2, 3])
    }
  </script>

In this code, we start by defining a couple of variables. An empty array that we will populate with a couple of Person objects and a name. We then have the constructor for the Person object. All it does is choose a name based on the index that is passed to it.

Next, we have the printName() function. It simply prints whatever value is in the name variable of whatever object is set to the current context. And finally, we have the go() function that is executed when the user presses the button.

The first thing we do when the button is clicked is call printName() directly. If you recall from earlier in this post, this is calling a function as a function. As a result, the context is the global window object and the name ‘alex’ is printed to the console. So far, so good.

Next, we set up a for loop and create 5 Person objects and push them into the people array.

Then we jump right into an array.forEach on our people array. During each iteration, we call printName.call() passing the current object as the context. This means that we are setting the context of the function dynamically. Pretty cool. This produces the following output in the console.

output for our dynamically set context

The first ‘alex’ in the output is from our earlier call to printName(). Each additional line of output is from iterating over the array.

This code demonstrates the call() method available on all functions. It looks very similar to object dot syntax because it is object dot syntax. All functions in JavaScript are objects.

The apply method is very similar. The only difference between the two is the arguments they accept. call() accepts a list of values while apply() accepts an array, like so:

//call accepts a list of values
printName.call(valueOfThis, 1, 2, 3);

//apply accepts an array of values
printName.apply(valueOfThis, [1, 2, 3]);

That wraps up this quick introduction of the 4 ways to call a JavaScript function. I find that I use all of these methods and knowing what’s happening under the hood is really helpful.

Keep in mind that in JavaScript, functions are first-class objects. They can have their own properties and methods and can be passed around just like other objects. This concept of functions as objects can take a bit of getting used to if you’re coming from another language like C# or Java. I know it took me a little bit to get my head wrapped around it.

Thanks for reading.