DEV Community

Robert Hieger
Robert Hieger

Posted on

A Quick Look at the JavaScript call() Method

Photo by James Harrison on Unsplash
Photo by James Harrison on Unsplash


JavaScript in Plain English

This article was originally published on JavaScript in Plain English


Table of Contents


Introductory Remarks

What This Tutorial Assumes

What Does the call() Method Do?

Now Let's Build It

    Step 1. Download the Starter Code

    A Brief Tour of the Starter Code

    Step 2. Declaring Objects to Reference the Desired HTML Elements

    Step 3. Create the 3 Dog Objects

    Step 4. Coding the getDogInfo Object

    Step 5. Using the call() method to specify the object whose properties we want returned as an Array

    Step 6. Implementing the resetTable() function

    Step 7. Implement the setRowContent() function

    Step 8. Implementing the event listeners

A Final Word

Works Citied



I found my way into full-stack web development from an atypical background. I am an actor, writer, director, and musician. Full-stack web development and design felt like a natural choice to me, as it provides the opportunity to exercise my imagination and express aesthetically in visual design for the web.

Like so many of us working in or studying software engineering and design, I am a firm believer in the idea that one of the best teachers is testing your skills by sharing that knowledge with others.

This is the first of three articles on three very useful methods exposed by the JavaScript function object—call(), bind(), and apply(). These methods are similar to one another, and thus can be a bit confusing.

The demo project in this article is not intended to be a treatise on the best and only way to employ the call() method. Rather, I intend to share my discovery in grappling with the difficulties one encounters when learning the call() method.

I have been a dog lover all my life. I thought it might be fun to create a web page that dynamically lists out some favorite dog breeds, their indigenous habitats, and their average lifespans in a table as seen below:

My Favorite Dogs Opening Screen

Fig. 1 Opening Screen of MY FAVORITE DOGS Demo

The object of this demo is to employ the call() method that function objects expose to extract properties from objects and assign them dynamically to text nodes in the Document Object Model (DOM).

I am a firm believer in the idea that one of the best teachers is testing your skills by sharing that knowledge with others.

In Figure 1, you see the opening screen of the finished product, which displays a table with space for three favorite dog breeds, the countries to which they are indigenous, and their average lifespans.

When the page is loaded, because no favorite dog has been selected, the three items of the BREED column contain the default text NO BREED SELECTED.

Below the table is a button bar with four buttons, the first three of which allow the user to add a first, second, and third favorite dog breed.

For the purposes of this demo, we will not seek the input of the user to enter favorite breeds. The three buttons dynamically fill in the three columns for each breed by assigning the properties of three dog breed objects to the table cell text nodes for each breed.

The fourth button resets the screen to its original state.

What This Tutorial Assumes

This tutorial assumes a basic understanding of HTML, a firm grasp of JavaScript basics, and some knowledge of Object Oriented Programming (OOP). Familiarity with Cascading Style Sheets (CSS) is desirable, but not required. The primary focus of this tutorial is JavaScript.

What Does the call() Method Do?

Aye, there's the rub. In order to benefit at all from the powerful call() method, you really have to have a clear understanding of what it does.

Let's start with the de facto resource for JavaScript study on the web—Mozilla Developer Network (MDN)—to get ourselves started:

The call() method calls a function with a given this value and any arguments provided to specify to which value this refers.

This is all very good, but what does it mean? The this keyword in JavaScript has been the cause for nightmares for many budding developers, myself included. It is subject to misinterpretation and especially in earlier JavaScript standards, can behave in very strange ways.

this, in theory, was supposed to refer to the calling function, but because the value of this cannot be set at the time of the function call, JavaScript will default to the value of the global context, which is window. This value will be returned, as shown in the example from the MDN article below:

MDN article on this keyword

Fig. 2 Excerpt from Mozilla Developer Network article on this keyword

As you can see in Figure 2, this rfefers to the global object, which is window. As the window does not yet refer to the context we need, which is document (the next level down) in the Document Object Model, there is no value for function f1() to return except undefined.

From the JavaScript code that is part of our project, this is specified, using the call() method, and referring to a specified object, as shown in Code Listing 1 below:

const getDogInfo = {
  info(): function {
    // Array containing properties of each dog object
    return [
      this.breed,
      this.origin,
      this.lifeSpan
    ];
  }
};

const dog1 = getDogInfo.info.call(breed1);
const dog2 = getDogInfo.info.call(breed2);
const dog3 = getDogInfo.info.call(breed3);
Enter fullscreen mode Exit fullscreen mode
Code Listing 1: Demonstration of call() Method Using Project Code



Code Listing 1 above shows an object literal named getDogInfo. Within the object is a function called info() that returns an array of the three properties present in three objects designated breed1, breed2 and breed3.

In the three statements that follow, the values associated with this are determined by specifying the objects to which this refers in the call() method chained to info, which in turn refers back to the info() method exposed by the getDogInfo object.

Is your head spinning yet? Don't worry. Mine did, for a while, too. Let's just take things step by step.

Now Let's Build It

Step 1. Download the Starter Code

Start by downloading the starter code.

You can follow along in the steps to finish the project. As the focus here is JavaScript, and not CSS styling or HTML, the starter code will provide the bare bones structure on which the tutorial project will be built.

When you download the starter code, you will find a zip archive as shown below in Figure 3:

The starter code

Fig. 3 Downloading the Starter Code

The screenshot above shows the zip archive in the Downloads folder on a Mac. If you are running Windows or another OS, the location of your download may differ.

Simply move the zip archive to the location you wish and unzip it.

Or if you prefer, you can clone the git repository, and begin by working with the starter code in the starter-code folder.

I urge you not to look at the finished-project folder until you have followed through the steps of this tutorial. This way, you can gain the best insights, as you piece the project together. That said, should you find yourself stuck, you can certainly check your code against that in the repository.

Once you unzip the starter code, you will find the following project files as shown below in Figure 4:

Screenshot of project files

Fig. 4 Project Files as Displayed in Visual Studio Code

A Brief Tour of the Starter Code

The starter code includes a css* folder with a CSS file—call-demo.css**—a file that provides the styling for the project.

In the js folder is a starter app.js JavaScript file, which will eventually contain all the logic for the tutorial.

Now that all our starter files are in place, we can dive into the project.

Step 2. Declaring Objects to Reference the Desired HTML Elements

In order to add content to an HTML page dynamically, you must identify and capture the elements that you wish to change or augment in a JavaScript DOM object.

Figure 5 below shows the relevant HTML that is part of your starter code:

HTML Listing

Fig. 5 HTML Listing—Elements to be Referenced

Figure 5 shows the elements that need to be referenced in the DOM. To do this, we must create JavaScript objects that point to the elements (or nodes, as they are known in the DOM).

Note that every <td> and <button> element above has an id attribute. Though there are many ways to access these nodes in the DOM using JavaScript, we will approach this using the simplest and most basic method of all—that is the getElementById() method.

Figure 6 below shows our starter app.js file, which will be the brain center of our project.

Starter Code app.js

Fig. 6 Starter code for app.js



To provide access to the DOM nodes, each of the breed columns and the buttons in the button bar must be stored in DOM objects. To do this, replace /* YOUR CODE HERE */ with the code in Code Listing 2 below:

const breedOne = document.getElementById('favBreed1');
const breedOrigin1 = document.getElementById('origin1');
const breedAvgLife1 = document.getElementById('avgLife1');

const breedTwo = document.getElementById('favBreed2');
const breedOrigin2 = document.getElementById('origin2');
const breedAvgLife2 = document.getElementById('avgLife2');

const breedThree = document.getElementById('favBreed3');
const breedOrigin3 = document.getElementById('origin3');
const breedAvgLife3 = document.getElementById('avgLife3');

const button1 = document.getElementById('breed1');
const button2 = document.getElementById('breed2');
const button3 = document.getElementById('breed3');

const button4 = document.getElementById('reset');
Enter fullscreen mode Exit fullscreen mode
Code Listing 2 Creating the DOM Objects

Now that we have created the necessary DOM objects, we can reference and manipulate them directly through JavaScript. To prove that we can gain access to any of the nodes thus captured by the DOM constants, you can use the JavaScript console of your browser to see what one of the DOM objects returns, as shown in Figure 7 below:

Console output for button4

Fig. 7 JavaScript Console Showing the Output of button4



Step 3. Create the 3 Dog Objects

The next leg of our journey brings us to the heart of the problem. We have created objects that reference the three tables rows that will contain information about our favorite dogs. But how do we get that information into a form that JavaScript can use to populate the rows?

There are several ways to do this. For the purposes of this tutorial, we declare 3 dog objects using the object literal syntax as shown below in Code Listing 3 below:

const breed1 = {
  breed: 'PUG',
  origin: 'CHINA',
  lifeSpan: '12-15 YEARS'
};

const breed1 = {
  breed: 'LABRADOR',
  origin: 'NEWFOUNDLAND',
  lifeSpan: '10-12 YEARS'
};

const breed3 = {
  breed: 'BEAGLE',
  origin: 'ENGLAND',
  lifeSpan: '12-15 YEARS'
};
Enter fullscreen mode Exit fullscreen mode
Code Listing 3 Declaring the Dog Objects

Code Listing 3 shows breed1, breed2 and breed3 objects with the properties breed, origin and lifeSpan defined. You might ask why I did not declare a Dog class and then instantiate three Dog objects from that.

While using classes is an efficient and elegant way to code the objects, the definition of individual object literals as shown above will demonstrate what the call() method does. In fact, the use of classes would obviate using the call() method, as properties and methods are incapsulated in one object.

In another tutorial, I will show the same project refactored to use class declaration and object instantiation.

You should now append the above code to the end of your app.js starter file.

We now have the raw materials we need. But how do we extract the properties from our breed _objects above and inject them, one-by-one, into the table cells defined above?

For this, we will need a function that gets this information and transforms it into a form we can use to inject the desired content.

Step 4. Coding the getDogInfo Object

Now we implement the getDogInfo object, whose sole property is a method called info. This method extracts the properties from our breed objects defined above, and returns an Array with the desired values from those properties. We already saw this object in Code Listing 1, but it is reproduced here for ease in reading. Code Listing 4 below is the implementation of the getDogInfo object:

const getDogInfo = {
  info: function() {
    // Array containing properties of each dog object
    return [
      this.breed,
      this.origin,
      this.lifeSpan
    ];
  }
};
Enter fullscreen mode Exit fullscreen mode
Code Listing 4 The getDogInfo Object



In Code Listing 4, we declare the getDogInfo object. the info() method returns an Array containing the dog object properties.

You should now append the code above to the end of your app.js starter file.

In order to make use of the returned Array, we will need to store the returned value of getDogInfo in a variable. This is what we will do next.

Step 5. Using the call() method to specify the object whose properties we want returned as an Array

Though the getDogInfo object and its info() method provide the logic to extract the object properties we need in order to inject the content on the web page, on its own, getDogInfo does not have the functionality to specify from which object we wish the property values returned.

Enter the call method, which is a prototype method exposed by all function objects. The basic syntax employed in the variable declarations needed at this point will take the following form:

const obj = getDogInfo.info.call(desiredObject);
Enter fullscreen mode Exit fullscreen mode

Let's pick this statement apart to clarify what it is doing. On the left side we declare a constant called obj and store to it the returned values from the getDogInfo object. Using object dot notation, we chain the info() method on getDogInfo, followed by the built-in call() method, which takes a single argument of the name of the object you wish referenced to this.

Code Listing 5 below shows the resulting code needed to return the desired Arrays of values:

const dog1 = getDogInfo.info.call(breed1);
const dog2 = getDogInfo.info.call(breed2);
const dog3 = getDogInfo.info.call(breed3);
Enter fullscreen mode Exit fullscreen mode
Code Listing 5 Using the call() Method



You should now append the code in Code Listing 5 to the end of your app.js starter file.

Now almost everything is in place, but there are still a few critical missing pieces. The first of these is a function that will be called by the RESET button that appears in Figure 1 at the beginning of this article. Its purpose is to return the table of dog breeds back to its original state after the other three buttons to its left have been clicked.

For this, we will build a function called resetTable().

Step 6. Implementing the resetTable() function

Code Listing 6 below shows the implementation of the resetTable() function, which performs a lot of behind-the-scenes work to reset our table to its beginning state:

const resetTable = () => {

  const noSelection = 'NO BREED SELECTED';

  breedOne.textContent = noSelection;
  breedOrigin1.textContent = null;
  breedAvgLife1.textContent = null;

  breedTwo.textContent = noSelection;
  breedOrigin2.textContent = null;
  breedAvgLife2.textContent = null;

  breedThree.textContent = noSelection;
  breedOrigin3.textContent = null;
  breedAvgLife3.textContent = null;

};
Enter fullscreen mode Exit fullscreen mode
Code Listing 6 The resetTable() Function



resetTable() is implemented as an arrow function, but it could just as easily have used the function myFunction() {} syntax that existed prior to ECMAScript 6. Either will work fine. I happen to prefer the elegant syntax of the arrow function.

A lot is going on here, but let's briefly pick this apart. You'll recall that in Figure 1, the leftmost column of the table is filled on each row with the content NO BREED SELECTED.

When the ADD FIRST FAVORITE, ADD SECOND FAVORITE and ADD THIRD FAVORITE buttons are clicked these entries are replaced with the name of the dog breed. Rather than individually specifying this value for each table row, it makes sense to declare a constant with the value, hence the constant noSelection that appears in the above listing.

As a reminder of what all the DOM objects in the above listing reference, you can refer both to Code Listing 2, and also the matching code in your index.html starter code.

In Code Listing 6, the textContent property of each of the defined DOM objects for each table row is set to its original value. In the case of the BREED column, the column is set to the value stored in the noSelection constant. The remaining two columns are simply set to null, removing the content injected when the first three buttons were clicked.

You should now append the code in Code Listing 6 to the end of your app.js starter file.

There is still one other critical function needed to set the content of each table row when the ADD FIRST FAVORITE through ADD THIRD FAVORITE buttons are clicked. This will be accomplished by the setRowContent() function that will act as a callback function to the buttons' associated event listeners, as will become evident in Step 8. But now, on to Step 7.

Step 7. Implement the setRowContent() function

Code Listing 7 below shows the implementation of the setRowContent() function:

const setRowContent = (
  column1,
  column2,
  column3,
  breed
) => {
  column1.textContent = breed[0];
  column2.textContent = breed[1];
  column3.textContent = breed[2];
};
Enter fullscreen mode Exit fullscreen mode
Code Listing 7 The setRowContent() function



As you can see, the setRowContent() function takes four arguments, one for each of the three columns in a table row, and a fourth to specify the object from which we will extract our needed properties. We pass these arguments to the function at runtime to populate each row of the table.

We are almost done now, but there is still one critical component missing. If you click on any of the buttons, absolutely nothing will happen. We need to wire the buttons to the functionality we have thus far defined. This is done, of course, by virtue of event listeners. We will define an event listener for the click of each button on the screen.

Step 8. Implementing the event listeners

And now we arrive at the last step to enable the dynamic content on our web page.

There are four buttons on the page, and thus we need four event listeners. The type of event for which we are listening is a click event when the user clicks on any of the four buttons.

Code Listing 8 below shows the implementation:

//  Button box event listeners populate
//  table with dog breed information.

button1.addEventListener('click', () => {
  setRowContent(
    breedOne,
    breedOrigin1,
    breedAvgLife1,
    dog1
  );
});

button1.addEventListener('click', () => {
  setRowContent(
    breedTwo,
    breedOrigin2,
    breedAvgLife2,
    dog2
  );
});

button1.addEventListener('click', () => {
  setRowContent(
    breedThree,
    breedOrigin3,
    breedAvgLife3,
    dog3
  );
});

button4.addEventListener('click', resetTable);
Enter fullscreen mode Exit fullscreen mode
Code Listing 8 The event listeners



As shown in Code Listing 8, an event listener is declared for each of the four buttons shown in Figure 1 at the beginning of this tutorial. In the first three event listeners, we use an anonymous function, which in turn calls the setRowContent(https://www.javascripttutorial.net/javascript-anonymous-functions/) function implemented in Step 7.

Because these are click events, when the user clicks on the button, the dynamic content attached to that button will be injected into the table rows and cells specified in the function call.

Finally, in the event listener for button4, we use a callback function—namely the resetTable() function defined earlier in Step 6.

Our project is now complete. If you want to see the project in action, you can find it on Codepen.

A Final Word

The end product is, of course, a bit artless, in that the user is only able to add the hard-coded properties of the three dogs included in the JavaScript code. In a real-world example, you would probably want a modal dialogue box to pop up asking a user to input the data for the favorite dog breed of choice.

You would almost certainly not want a pre-determined number of rows in the table, but only add the rows to the table dynamically as a user enters choices. I plan to build this more elaborate application and post a tutorial for it in the near future.

The purpose of this tutorial, however, is to provide a working, and at least somewhat meaningful example of how the call() function, exposed by the built-in JavaScript function object, works. I am open to any suggestions for future articles or projects.

I hope you have found this tutorial enjoyable.


Works Cited

"this - JavaScript | MDN", _Mozilla Developer Network, Mozilla Foundation,
        25 Sept. 2023, https://developer.mozilla.org/en-US/docs/Web/
JavaScript/Reference/Operators/this
.

"Property Accessors - JavaScript | MDN." Mozilla Developer Network,
        Mozilla Foundation, 6 Sept. 2023, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#dot_notation.

"JavaScript Anonymous Functions." JavaScript Tutorial,
        https://www.javascripttutorial.net/javascript-anonymous-functions/.
        Accessed 22 Oct. 2023.

Top comments (0)