DEV Community

loading...

Classes in JavaScript

Joe Christensen
Software Engineer writing helpful blogs on Dev.to. Reach out if you want me to write something specific!
Updated on ・5 min read

Alt Text

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 {
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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?
Enter fullscreen mode Exit fullscreen mode

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!`;
  }

}
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (11)

Collapse
lukeshiru profile image
LUKESHIRU

Leaving my opinion about classes aside for a sec, you can actually declare private properties in a JS class like this:

class Example {
  #aProp = "value"
  getAProp() {
    return this.#aProp;
  }
}

const example = new Example()

example.#aProp; // Error!
example.getAProp(); // Works
Enter fullscreen mode Exit fullscreen mode

Here's more information about that if you want to use it to update your article.

If you actually wonder how you can write code without classes, take a look at the functional programming paradigm with JavaScript. Trust me, I used to do everything with classes and now I never use them.

Cheers!

Collapse
christensenjoe profile image
Joe Christensen Author

Thank you for the added information! I'll update my article when I get the chance.

Do you know when JavaScript actually introduced private class properties?

Collapse
lukeshiru profile image
LUKESHIRU

Based on this it was proposed back in 2015, and it was added to the browsers in 2019 afaik (at least in it was added in Chrome 74).

Collapse
djuric profile image
Žarko Đurić

Any books/resources you would recommend on functional programming with JavaScript?

Collapse
lukeshiru profile image
LUKESHIRU

One that I read and quite good and focused mainly in JS is called Composing Software by Eric Elliot. My recommendation is to just read about functional programming in general, with stuff like pure functions, immutability, currying and so on, which seem complex but are actually quite simple, and then try to work in JS applying those principles and without using classes at all.

Collapse
klajdi44 profile image
Klajdi Ajdini

Really nice article!

Collapse
christensenjoe profile image
Joe Christensen Author

Thank you!

Collapse
juanfabiorey profile image
juanfabiorey

Thanks a lot!

Collapse
jakeb1090 profile image
jakeb1090

Sometimes I see properties declared inside the constructor and methods on the outside. What is the difference between declaring methods within the constructor vs outside the constructor?

Collapse
ericdecol profile image
punk croc

Bad code. It should be outsite for organization. You can call it inside the constructor if you want it to run when instantiating a class, but it's creationg should be elsewhere, in a more organized way