Table of Contents
Classes in JavaScript provide a blueprint for the creation of objects. This means that once you define a class (including its member variables and methods), you can endlessly create new objects from it. This is useful because it allows us to reduce the amount of code we need to write when we want multiple objects that are similar to one another. This is also useful because it allows us to reuse code.
Defining a Class
Defining a class in JavaScript is simple thanks to the built-in class
keyword. Let's say we run a pet store and want a JavaScript object to represent each pet. Thus, we can create a Pet
class.
JAVASCRIPTclass Pet {
}
const pet = new Pet();
console.log(pet);
HTMLPet {}
We have created a new Pet
object using our defined class, assigned it to the pet
variable, and printed it out.
But let's make our Pet
class useful.
Constructing a Class
How you construct a class is just going to depend on what you need the class to do. In our case, since they represent a pet in a pet store, we should probably have variables for the pet's name, weight (in pounds) and price (in USD).
JAVASCRIPTclass Pet {
constructor(name, weight, price) {
this.name = name;
this.weight = weight;
this.price = price;
}
printInfo() {
return "Hi, my name is " + this.name + ". I weigh " + this.weight + " pounds and cost $" + this.price + ".";
}
}
const pet = new Pet("Fluffy", 20, 200);
console.log(pet);
console.log(pet.printInfo());
HTMLPet {
name: "Fluffy",
weight: 20,
price: 200
}
Hi, my name is Fluffy. I weigh 20 pounds and cost $200.
In this case, we are using the constructor
keyword. You can think of constructor
as just a special function that asks for the data required to create a new object out of the class. Since we want every pet to have a name, weight and price, we are specifying that in our constructor.
If you noticed, we also defined a printInfo
function that simply returns back a user-friendly string that describes the pet.
As mentioned before, the cool thing about classes is that you no longer need to define multiple objects but instead can use one common class. Look how easy it would be to define three different pets:
JAVASCRIPTclass Pet {
constructor(name, weight, price) {
this.name = name;
this.weight = weight;
this.price = price;
}
printInfo() {
return "Hi, my name is " + this.name + ". I weigh " + this.weight + " pounds and cost $" + this.price + ".";
}
}
const pet1 = new Pet("Oreo", 15, 300);
console.log(pet1.printInfo());
const pet2 = new Pet("Dashy", 25, 400);
console.log(pet2.printInfo());
const pet3 = new Pet("Ninja", 20, 350);
console.log(pet3.printInfo());
HTMLHi, my name is Oreo. I weigh 15 pounds and cost $300.
Hi, my name is Dashy. I weigh 25 pounds and cost $400.
Hi, my name is Ninja. I weigh 20 pounds and cost $350.
Class Inheritance
While our current solution works for now, it can certainly be improved upon. Our Pet
class doesn't offer any distinction between a cat or a dog, which each would have additional information that doesn't apply to the other. Luckily for us, JavaScript offers class inheritance, which means we can create new classes that inherit everything from another, but adds unique information for itself.
This means that since a dog is still a pet, we can just inherit from the Pet
class and add any dog-specific stuff in the Dog
class. To keep things basic, let's add the ability to bark if it's a dog.
JAVASCRIPTclass Dog extends Pet {
bark() {
console.log("BARK BARK BARK");
}
}
const dog = new Dog("Cooper", 20, 200);
console.log(dog.printInfo());
dog.bark();
HTMLHi, my name is Cooper. I weigh 20 pounds and cost $200.
BARK BARK BARK
We created a new Dog
, but since it is still a pet because we inherited from the Pet
class, it was able to both bark
, something only dogs can do, but also return back info thanks to the printInfo
function, something any pet can do.
The information we passed to the Dog
class is automatically passed to the Pet
class which is how printInfo
worked as expected.
Function Overriding and Super Keyword
To serve as an introduction to another useful JavaScript feature, let's create a Cat
class. This time, we'll have all cats have a unique feature that they each have a favorite brand of cat food, and thus will need a string to keep track of that.
JAVASCRIPTclass Cat extends Pet {
constructor(name, weight, price, brand) {
super(name, weight, price);
this.brand = brand;
}
getFavoriteBrand() {
return this.brand;
}
printInfo() {
return "Hi, I'm a cat named " + this.name + " and I like " + this.brand + ". I weigh " + this.weight + " pounds and cost $" + this.price + ".";
}
}
const honey = new Cat("Honey", 15, 300, "Purina");
console.log(honey.printInfo());
console.log(honey.getFavoriteBrand());
HTMLHi, I'm a cat named Honey and I like Purina. I weigh 15 pounds and cost $300.
Purina
A couple of very interesting things is happening here. First, in the constructor for Cat
, you'll notice the super
keyword. This is simply manually calling the constructor of the class that Cat
is inheriting from, in this case, the Pet
class. The only reason this is needed is because we added a new parameter to the constructor of Cat
, and that is the brand
string.
Since brand
is unique to cats, we assign it under the super
call.
The second interesting thing that is happening here is that we defined a printInfo
function inside Cat
, even though there is already one inside Pet
. When we do this, we are overriding the function, which means that cats will use the one defined in Cat
instead of Pet
, which is what we want.
Classes in JavaScript are extremely useful and versatile, as these examples have hopefully shown. You can define base classes (the Pet
class) and create an endless number of classes that inherit from it (the Dog
and Cat
classes) which have their own unique features and functionality only private to them, which still retaining the features and functionality available to all.
You could even go further and have different breeds of dogs and cats have their own classes that inherit from the Dog
and Cat
class!
Private Class Fields
Relatively new to JavaScript are private class fields. A class field is a variable that is maintained inside a class. Previously, there was no way to denote that a field should only be accessible to the class itself and not for outsiders. We got around this limitation by adding an underscore in the variable name. Here's an example:
JAVASCRIPTclass Number {
_value = 0;
increment() {
this._value++;
}
}
To other developers, the underscore would imply that the variable is only meant to be accessed internally, but nothing prevented you from doing this in another file:
JAVASCRIPTconst number = new Number();
console.log(number._value);
HTML0
However, with the introduction of truly private class fields, we can let JavaScript enforce this for us:
JAVASCRIPTclass Number {
#value = 0;
increment() {
this.#value++;
}
}
Now if you try doing the same thing as before and try to access the variable directly, you will get an error:
JAVASCRIPTconst number = new Number();
console.log(number.#value);
HTMLUncaught SyntaxError: Private field '#value' must be declared in an enclosing class
Resources
- Getting Started with Solid
- Getting Started with Express
- How to Serve Static Files with Nginx and Docker
- Best Visual Studio Code Extensions for 2022
- How to deploy a Deno app using Docker
- How to deploy an Express app using Docker
- How to deploy a Node app using Docker
- Learn how to use v-model with a custom Vue component
- Using Puppeteer and Jest for End-to-End Testing
- How to Scrape the Web using Node.js and Puppeteer
- Build a Real-Time Chat App with Node, Express, and Socket.io
- Getting Started with Vuex: Managing State in Vue