Photo by Negative Space from Pexels
This article was first published on Javascript in Plain English
Table of Contents
Introduction
Let's Get Started
What Needs to Change?
Now Let's Refactor the Code
Step 1: Make the Needed Changes to index.html
Step 2: Rename the CSS Style Sheet
Step 3: Refactor the breed Objects
Step 4. Refactor the dog Objects to use the bind() Method
How Does Function.prototype.bind() Differ from Function.prototype.call()?
What's Next?
Works Cited
Introduction
It has been a while, and I am happy top get back to my promised series of tutorials. This is the second in a series of three tutorials on a project to demonstrate the call()
, bind()
and apply()
methods, which bear similarities, but also have distinct differences.
The first tutorial in this series covered the use of the call()
method in a project that populated a table of favorite dog breeds on the click of buttons beneath the table.
The text editor used in this tutorial is Visual Studio Code (VSC), a very powerful, yet easy-to-use extensible programmer's editor by Microsoft. And it is absolutely free. However, you can use your favorite text editor instead, as long as it features code syntax highlighting for JavaScript, as this will ease in reading your code, and preferably "IntelliSense" to anticipate the code you intend, after a few keystrokes.
In this second of three tutorials, we will take a look at the bind()
method, which bears similarity to the call()
method.
The code in this project will produce output identical to that of the first tutorial, but using the bind()
method instead. This will require several changes to the code from the previous tutorial.
PREREQUISITE: If you have not already gone through the first tutorial in this series, because a good deal of the code will not be reviewed here, you would do best to review A Quick Look at the JavaScript call() Method.
As we have already built a functioning model of the finished project (as shown below in Figure 1), our focus in this tutorial will not be a walkthrough of the entire process, but rather an exploration of the differences in code for this version of the project.
Fig. 1 Opening Screen of My Favorite Dogs
For a brief recap, in the first tutorial, we built a very simple single page application (SPA) with four buttons, the first three of which allowed a user to populate three rows of a table with data on favorite dog breeds. The fourth button reset the table to its original state as shown above.
Let's Get Started
To get started, please download the tutorial starter code. Simply click the download icon found in the Github Link as shown below in Figure 2:
Fig. 2 Download Starter Code
You can unzip the archive onto your local drive and you will see the project files as shown in Figure 3 below:
Fig. 3 Starter Code Project Files
Figure 3 shows a directory tree with a css folder containing the external stylesheet for the project, a js folder to contain the application logic, and finally the index.html file with the application content.
What Needs to Change?
Several things must change to refactor this application to use the bind()
method, some trivial and some a bit more involved.
We will need to make changes in all three files that make up the application. In index.html the file reference to the external stylesheet will change for semantic reasons, as will the content in the <title>
tag.
Then, refactoring will occur in the code shown below in Code Listing 1:
const dog1 = getDogInfo.info.call(breed1);
const dog2 = getDogInfo.info.call(breed2);
const dog3 = getDogInfo.info.call(breed3);
Code Listing 1 Calls to getDogInfo
The code in Code Listing 1 above will be refactored to use the bind()
method. This will require an additional segment of code due to the difference between the call()
and bind()
methods.
Now Let's Refactor the Code
Armed with knowledge of the outlined changes above, we can refactor the code to demonstrate use of the bind()
method.
Step 1: Make the Needed Changes to index.html
Code Listing 2 below shows the <head>
section of the index.html file included in your starter code:
<head>
<meta charset="utf-8">
<meta http-equiv="x-UA Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>call() Method Demo</title>
<script src="./js/app.js"></script>
<link rel="stylesheet" href="./css/call-demo.css">
</head>
Code Listing 2 Section of index.html
We are concerned only with two lines in Code Listing 2.
Make the changes below to your starter code:
1) Change the line with the <title>
tag so that it reads as follows:
<title>bind() Method Demo</title>
2) Change the line with the <link>
tag to read as follows:
<link rel="stylesheet" href="./css/bind-demo.css">
Step 2: Rename the CSS Stylesheet
Referring back to Figure 3, you will see that CSS style sheet is named call-demo.css. This name does not match the name of the style sheet referenced in our revised <link>
tag.
Rename call-demo.css to bind-demo.css.
If you open **index.html in your browser, everything will display correctly. In fact, if you click the buttons of the app, they will function exactly as they did in the previous tutorial. This is due to the original code in our starter files for the project.
Now we have set the stage. Take a deep breath and let's dig into refactoring the application logic found in app.js so that it takes advantage of the
bind()
method instead of thecall()
method.
Step 3: Refactor the breed Objects
Code Listing 3 below shows the relevant code for this step:
const breed1 = {
breed: 'PUG',
origin: 'CHINA',
lifeSpan: '12-15 YEARS'
};
const breed2 = {
breed: 'LABRADOR',
origin: 'NEWFOUNDLAND',
lifeSpan: '10-12 YEARS'
};
const breed3 = {
breed: 'BEAGLE',
origin: 'ENGLAND',
lifeSpan: '12-15 YEARS'
};
Code Listing 3 The breed Objects
As Code Listing 3 shows, there are three sequentially numbered breed
objects that contain the properties that will be dynamically injected into the columns of the table in our app.
There is absolutely nothing wrong with the code above and it would work just fine for the purposes of this demo. But I am going to ask you to change the above three objects so that they look like the code in Code Listing 4 below:
const breed1 = {
breed: 'pug',
origin: 'china',
lifeSpan: '12-15 years'
};
const breed2 = {
breed: 'labrador',
origin: 'newfoundland',
lifeSpan: '10-12 years'
};
const breed3 = {
breed: 'beagle',
origin: 'england',
lifeSpan: '12-15 years'
};
Code Listing 4 Breed Objects Refactored
You might be asking yourself, "Why is this necessary?" And from a certain point of view, you would be correct. I chose to refactor this code for the following reasons:
As will be seen in the code that follows, refactoring this code as shown above cedes control of the typography to the application logic, rather than hard-coding the uppercase letters.
Later on, especially if this application were to be developed into a more functional model that accepted user input, all manner of characters a user might enter could then be cleaned up view transformation of the raw data entered by the user.
In essence, this kind of behavior is more far-reaching and geared toward further development of this simplistic demo.
Step 4. Refactor the dog Objects to the use the bind()
Method
Code Listing 5 below shows the code relevant to our task:
const getDogInfo = {
info: function() {
// Array containing properties of each dog object
return [
this.breed,
this.orgin,
this.lifeSpan
];
}
};
const dog1 = getDogInfo.info.call(breed1);
const dog2 = getDogInfo.info.call(breed2);
const dog3 = getDogInfo.info.call(breed3);
Code Listing 5 The getDogInfo Object and the Derived dog Objects
To clarify how we will refactor the above, let's review the code in Code Listing 5 to clarify what is happening in this listing.
The getDogInfo
Objet contains a single property, a method called info()
, whose sole purpose is to return the values that it will get, albeit indirectly, from the breed
objects. Note that the values returned correspond directly to the properties within the breed
objects shown in Code Listing 4 (the refactored breed
objects).
In Code Listing 5, three dog
objects are created using the call()
method. In this case, the object created is an array containing the values of the properties. But how does this differ from what we will do when we refactor this code?
How Does Function.prototype.bind() Differ from Function.prototype.call()?
A Brief Explanation. If you are looking for a thorough explanation of just how both these methods work, you'll find the most complete information at the Mozilla Developer Network page for Function.prototype.call() and Function.prototype.bind().
A simpler summary of the differences can be expressed like this:
The
call()
method invokes a function object and takes an argument that specifies to which object thethis
keyword refers. Additional arguments may also be added within thecall()
method signature.The
bind()
method, unlike thecall()
method, returns a brand new function which may be called, and through which you may pass an array and as many arguments as needed.
To refactor some of the code in Code Listing 5, revise the last three lines for objects dog1
through dog3
, so that they look like the code in Code Listing 6 below:
const dog1 = getDogInfo.info.bind(breed1);
const dog2 = getDogInfo.info.bind(breed2);
const dog3 = getDogInfo.info.bind(breed3);
Code Listing 6 Refactored dog Objects
So far, the only different is that we substituted bind()
for call()
in the three refactored declarations above.
But now comes the real difference. Now you should input the code below in Code Listing 7:
// Dog Data Arrays
const dogBreed1 = dog1();
const dogBreed2 = dog2();
const dogBreed3 = dog3();
Code Listing 7 dog Functions Invoked and Their Properties Stored
Why this extra step? Remember that what the bind()
method does is to return a brand new function. An array and any number of arguments may be passed to this new function. For the purposes of our project, we will make use only of an array. But this array must be stored as a constant from which it may be accessed. The three lines of code in Code Listing 7 achieve this.
With the creation of the three constants shown in Code Listing 7, we have finished our refactoring of the application.
To see the newly-refactored app in action, simply load the index.html file into your browser. You will find that its functionality is identical to that of the application in the first tutorial of this series.
Or you can visit the finished refactored application on codepen.io.
What's Next?
The third tutorial in this series will refactor this application once again to take advantage of the apply()
method. As you will see, this method also bears some similarity to the bind()
method. We will explore those differences as we refactor the application using this last of the three methods mentioned in the first tutorial.
See you soon in the next tutorial, A Quick Look at the JavaScript apply() Method.
Works Cited
Hieger, Robert. “A Quick Look At The Javascript call() Method.” Dev,
DEV Community, 31 July 2021, https://dev.to/rhieger/a-quick-look-at-the-javascript-call-method-5ghc.
“Function.Prototype.call() -Javascript | MDN.” Mozilla Developer
Network, Mozilla Foundation, 26 Sept. 2023, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call.
“Function.Prototype.bind() - Javascript | MDN.” Mozilla Developer Network,
Mozilla Foundation, Aug. 2023, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind.
Top comments (0)