Classes in JavaScript

What are Classes?

A class is an object-oriented programming concept that is built into many object-oriented programming languages. Specifically, a class is a blueprint for creating objects, initializing data, and defining functions. It is a way of organizing information about a type of objects in a reusable format. By using a class, a programmer can create specific instances of said class and access class-specific data and functions.

As an example, say a you wanted to create cat, dog, and bunny objects. You could create each individually, copying near identical code for each new object, or you could create a template called animal. Then, you could simply create your cat, dog, and bunny objects by passing special information into the animal template. Classes are this concept of using templates to create different but similar objects without having to re-type code.

Classes in JavaScript

With the update to ES6 in 2015, JavaScript has also gained class functionality. Although it is not as fleshed out and detailed as in other object-oriented languages, it is still there none-the-less.

In JavaScript, we declare the creation of a new class using the class keyword followed by a capitalized class name and a pair of curly brackets as shown:

class Animal {
}

In order to actually make use of this class, however, we need to make an instance of it. We do this by creating a variable and initializing it to our class using the new keyword like so:

class Animal {
}

let dog = new Animal();

Now we have dog, an instance of our animal class. But... what exactly can we do with it? Well, what kind of specifications does every animal have? A name, species, and age. In order to add this information to our animal class, we must create a constructor like so:

class Animal {
  constructor(name, species, age) {
  this.name = name;
  this.species = species;
  this.age == age;
  }
}

let dog = new Animal("Spot", "Dog", 4);

This constructor takes in the information given when initializing a new instance of the class (where we create our Dog object), and sets our Animal's class-specific variables, or properties, to it. Let's access and log some of our Dog's data by using dot notation.

class Animal {
  constructor(name, species, age) {
  this.name = name;
  this.species = species;
  this.age == age;
  }
}

let dog = new Animal("Spot", "Dog", 4);

console.log(dog.name) //returns "Spot"
console.log(dog.species) //returns "Dog"
console.log(dog.age) //returns 4

Now lets add a class-specific function that makes use of our class data to create a special message.

NOTE: Class-specific functions are called methods and don't require the function keyword.
class Animal {
  constructor(name, species, age) {
  this.name = name;
  this.species = species;
  this.age == age;
  }

  cutePet() {
  return `Aww, your ${this.species} is so cute!`;
  }

}

let dog = new Animal("Spot", "Dog", 4);

console.log(dog.cutePet()); //returns "Aww, your Dog is so cute!"

Once initialized, an instance of a class can access its methods the same way it accesses class properties, by using dot notation. But now that we have a basic class with some variables and methods, we can test the real usefulness of classes.

class Animal {...}

let dog = new Animal("Spot", "Dog", 4);
let bird = new Animal("Feathers", "Bird", 3);
let cat = new Animal("Mochi", "Cat", 2);

console.log(dog.cutePet()); //returns "Aww, your Dog is so cute!"
console.log(bird.cutePet()); //returns "Aww, your Bird is so cute!"
console.log(cat.cutePet()); //What does this return?

We initialized some new instances of our animal class called bird and cat like shown. Knowing what dog.cutePet() and bird.cutePet() return, what would calling cat.cutePet() return?

You guessed it! It would return "Aww, your Cat is so cute!". It accesses the same method we defined in our Animal class, except it uses the data provided when initializing the cat instance.

Public vs. Private

Most classes have the concept of public and private variables. A public variable is one that programmers are allowed to access directly, while a private one is meant to be inaccessible outside of a class's scope. Making use of these, programmers can better implement one of the major practices of object-oriented programming: Encapsulation.

While many object oriented languages have public and private keywords, the latest version of JavaScript does it a little differently. JavaScript class properties are declared public by default, meaning that programmers only have to specify when declaring private properties. We can declare a private class variable by adding a # to the front of every property declaration. When trying to access a private class property outside the class, JavaScript will return a [#variableName] out of scope syntax error. Check out the MDN documentation on private class properties to learn more.

NOTE: Until the introduction of private class features, JavaScript programmers simulated private class variables by adding an underscore to the front of a property name. Adding an underscore did not actually prevent programmers from accessing and changing these variables. It just lets programmers know to treat them as private.

Accessor Methods

JavaScript provides special built in methods called accessor methods that allow us to achieve better data quality, simpler syntax, and more security when accessing the properties of a class. Two common accessors are Getters and Setters.

Getter Method

One common accessor method is a getter. A getter method is one that returns a value, but lets us access it like we would a property. In order to make a getter, we must make sure that our method:

  • has a return statement
  • uses the get keyword
  • does not have any parameters

Following these conditions, we declare a getter method like so:

class Animal {
  constructor(name, species, age) {...}

  get cutePet() {
  return `Aww, your ${this.species} is so cute!`;
  }

}

Although it doesn't look like much, adding that get keyword means that we can now access that method as a property like this:

class Animal {...}

let dog = new Animal("Spot", "Dog", 4);

/**
console.log(dog.cutePet()) 
We no longer need these parentheses as it isn't 
a function call anymore.
**/
console.log(dog.cutePet); //returns "Aww, your Dog is so cute!"

Setter Method

Another common JavaScript accessor method is a setter method. A setter method follows the same logic as a getter. Instead of having to invoke a given method as a function, we can access it as a property of a given class. In order to make a setter, we must make sure that our method:

  • uses the set keyword
  • has a single parameter

Lets create a new setter method inside of our Animal class that changes the species of our animal.

class Animal {
  constructor(name, species, age) {...}

  get cutePet() {...}

  set animalName(name) {
    this.name = name;
  }
}

Now we can change our dog's name like so:

class Animal {...}

let dog = new Animal("Spot", "Dog", 4);

console.log(dog.name); //returns "Spot"

dog.animalName = "Fuzzy";

console.log(dog.name); //returns "Fuzzy"

As you can see, we can now access our animalName setter like we would a property and "set it equal" to a value. That value is automatically passed as a parameter to our setter method. If we didn't have our set keyword, we would instead have to invoke the function like this:

class Animal {...}

let dog = new Animal("Spot", "Dog", 4);

console.log(dog.name); //returns "Spot"

dog.animalName("Fuzzy");

console.log(dog.name); //returns "Fuzzy"

Final Statements

JavaScript Classes are powerful tools that help create better, modularized, reusable, and cleaner code. And you now have the abilities to use them! If you want to research more into classes and how they work in JavaScript, take a look at the MDN Documentation on Classes.

19