Empowering classes with instance methods
If you think back to the chapter on classes, we used them to create objects with certain properties. Now that you've started to learn about functions, you can add instance methods to these classes, enhancing their power and usefulness.
An instance method is a function which is part of a class, and acts on an instance of that class. Let's imagine a BankAccount
class:
class BankAccount {
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
}
}
You could then create an instance of this class called newAccount
:
const newAccount = new BankAccount('Will Alexander', 500);
As it stands, the instance can't do much. You could log its balance to the console using newAccount.balance
, but what if you wanted to add some formatting? You can add a method to the class!
class BankAccount {
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
}
showBalance() {
console.log('Balance: ' + this.balance + ' EUR');
}
}
The above new method, declared by its name followed by ()
, uses the this
keyword to access the instance's balance
field, and log it to the console with extra formatting. This means that you can use dot notation on the newAccount
instance to call its showBalance()
method:
const newAccount = new BankAccount('Will Alexander', 500);
newAccount.showBalance(); // prints 'Balance: 500 EUR' to the console
You can also add methods, which can modify the instance's properties; in this case, add deposit()
and withdraw()
methods to the class, remembering that they will both need an amount
parameter (as you need to know how much to deposit or withdraw!):
class BankAccount {
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
}
showBalance() {
console.log('Balance: ' + this.balance + ' EUR');
}
deposit(amount) {
console.log('Depositing ' + amount + ' EUR');
this.balance += amount;
this.showBalance();
}
withdraw(amount) {
if (amount > this.balance) {
console.log('Withdrawal denied!');
} else {
console.log('Withdrawing ' + amount + ' EUR');
this.balance -= amount;
this.showBalance();
}
}
}
The deposit()
method logs the deposit amount
to the console, adds the amount
to the instance's balance
, and then calls the instance's showBalance()
method, therefore printing the new balance
to the console.
The withdraw()
method checks if the amount
requested is greater than the current balance
. If so, it refuses the withdrawal; otherwise, it allows it, subtracting the amount
from the balance
and logging the new balance
to the console.
Now let's see how you can use instance methods to enrich the video streaming app.
Practice instance methods!
Head to CodePen Exercise P3CH2a and follow the instructions below.
Instead of using a function to calculate the average rating for a show, we have decided that the Show class should handle new ratings automatically. As you can see, the Show class starts with an empty ratings Array and an averageRating of 0.
Declare an instance method in the Show class called addRating(). It will take a rating (a number between 1 and 5) as a parameter.
The addRating() method must:
add the received rating to the instance's ratings Array;
recalculate the instance's averageRating value.
Hit the "Check ratings" button to see if the shows update properly. You can click the "Check ratings" button multiple times to watch the evolution of the shows' average ratings.
Solution:
Once you've given it a go, watch me code a solution and see how your approach compares. And here is a new CodePen with a solution to the exercice.
Static methods
There is a special type of method you can add to a class: static. These differ from instance methods because they are not linked to a specific instance of a class, but to the class itself. Use them to create helper methods where you do not need an instance of a class to use them.
For example, in JavaScript, the Math
object contains lots of useful methods:
const randomNumber = Math.random(); // creates random number on the interval [0, 1)
const roundMeDown = Math.floor(495.966); // rounds down to nearest whole number, returns 495
You don't need to create a new
instance of the Math
object to use these methods, you simply call them on the global Math
object.
You can create your own static methods with the static
keyword!
Consider the following class:
class BePolite {
static sayHello() {
console.log('Hello!');
}
static sayHelloTo(name) {
console.log('Hello ' + name + '!');
}
static add(firstNumber, secondNumber) {
return firstNumber + secondNumber;
}
}
BePolite.sayHello(); // prints 'Hello!'
BePolite.sayHelloTo('Will'); // prints 'Hello Will!'
const sum = BePolite.add(2, 3); // sum = 5
You don't need to add a constructor
to your class, as you are not going to instantiate it. You have a method which:
Prints a generic message.
Accepts an argument and uses it to generate a message.
Returns a value based on the arguments you send it.
All of these different functionalities could be left to functions — the advantage of using static class methods is to group them by category or type, for example.
Let's recap!
In this chapter, we looked at two types of class method:
Instance methods, which act upon individual instances of a class.
Static methods, which do not rely on an instance of a class.
In the next chapter, we're going to look at how to write clean functions and code in a way which will be easy to read, maintain, and adapt!