The Classy Way to Create Objects in JavaScript

by kirupa   |   17 June 2017

When it comes to working with objects, we have covered a lot of ground so far. We saw how to create them, we learned about prototypical inheritance, and we even looked at the dark art of extending objects as well. In doing all of this, we worked at a very low level and were exposed to how the object-flavored sausage is made. That's great for really understanding what is going on. That's not so great when making sense of complex object happenings in your app. To simplify all of this, with the ES6 version of JavaScript, you have support for this thing called classes.

Those of you with a background in other object-oriented programming languages are probably familiar with that term. Don't worry if you are not. In the world of JavaScript, classes are nothing special. They are nothing more than just a handful of new keywords and conventions that simplify what we have to type when working with objects. In the following sections, we'll get a taste of what all that means.

Onwards!

The Class Syntax and Object Creation

We are going to learn about the class syntax the same way our grandparents did - by writing code. Because there is a lot of ground to cover, we won't try to bite off everything at once. We'll start by focusing on how to use the class syntax when creating objects. As you'll see, there is a lot going on there that will keep us plenty busy!

Creating an Object

You can think of a class as a template - a template objects refer to when they are being created. Let's say that we want to create a new class called Planet. The most basic version of that class will look as follows:

class Planet {

}

We use a keyword called class followed by the name we want to give our class. The body of our class will live inside curly brackets, { and }. As you can see, our class is currently empty. That's not very exciting, but it is OK for now. We want to start off simple.

To create an object based on this class, all you need to do is the following:

var myPlanet = new Planet();

We declare the name of our object and use the new keyword to create (aka instantiate) our object based on the Planet class. If we had to visualize what is happening under the hood, here is what you would see:

This looks a bit different than what we saw when creating objects using Object.create(). The difference has to do with us creating our myPlanet object by using the new keyword. When we create objects with the new keyword, the following things happen:

  1. Our new object is simply of type object. It doesn't become the type of the class (like Planet)
  2. Our new object's [[prototype]] is our newed function or class's [[prototype]]
  3. A constructor (usually a function or method) gets executed that deals with initializing our newly created object
  4. The value of this is set to the newly created object

I won't bore you too much with additional details, but there is one important thing that we are going to dive into further. That thing deals with the so-called constructor that we mentioned in the 3rd item above.

Meet the Constructor

The constructor is a function (or method) that lives inside your class's body. It is responsible for initializing the newly created object, and it does that by running any code contained inside it during object creation. This isn't an optional detail. All classes must contain a constructor function. If your class doesn't contain one (kinda like our Planet right now), JavaScript will automatically create an empty constructor for you.

Let's go ahead and define a constructor for our Planet class. Take a look at the following modification:

class Planet {
  constructor(name, radius) {
    this.name = name;
    this.radius = radius;
  }
}

To define a constructor, we use a special constructor keyword to create what is basically a function. Just like a function, you can also specify any arguments you would like to use. In our case, we specify a name and radius value as arguments and use them to set the name and radius properties on our object:

class Planet {
  constructor(name, radius) {
    this.name = name;
    this.radius = radius;
  }
}

You can definitely do a lot more (or a lot less!) interesting things from inside your constructor, but the main thing to keep in mind is that this code will run every single time we are creating a new object using our Planet class. Speaking of which, here is how you call our Planet class to create an object:

var myPlanet = new Planet("Earth", 6378);
console.log(myPlanet.name); // Earth

Notice that the two arguments we need to set on our constructor are actually set directly on the Planet class itself. When our myPlanet object gets created, the constructor is run and the name and radius values we passed in get set on our object:

While we are learning about the class syntax and the details surrounding it, never forget that all of this is just frosting - delicious syntactic sugar designed to make your life easy. If we didn't use the class syntax, we could also have done something like this:

function Planet(name, radius) {
  this.name = name;
  this.radius = radius;
};

var myPlanet = new Planet("Earth", 6378);
console.log(myPlanet.name); // Earth

The end result is almost identical to what we gained with the class syntax. How we got there is the only thing that is different. Don't let this comparison give you the wrong impression, though. Other useful uses of the class syntax won't be as easy to convert using the more traditional approaches as we've seen here.

What Goes Inside the Class

Our class objects look a lot like functions, but they have some quirks. We saw that one of the things that goes into the body of your class is this special constructor function. The only other things that can go inside your class are other functions/methods, getters, and setters. That's it. No variable declarations and initializations are welcome.

To see all of this at work, let's add a getSurfaceArea function that prints the surface area of our planet to the console. Go ahead and make the following change:

class Planet {
  constructor(name, radius) {
    this.name = name;
    this.radius = radius;
  }

  getSurfaceArea() {
    var surfaceArea = 4 * Math.PI * Math.pow(this.radius, 2);
    console.log(surfaceArea + " square km!");
    return surfaceArea;
  }
}		

You call getSurfaceArea off our created object to see it in action:

var earth = new Planet("Earth", 6378);
earth.getSurfaceArea();

When this code runs, you'll see something like 511 million square kilometers printed out. That's good. Since we mentioned the other things that can go inside our class body are getters and setters, let's throw those in as well. We'll use them to help us represent our planet's gravity:

class Planet {
  constructor(name, radius) {
    this.name = name;
    this.radius = radius;
  }

  getSurfaceArea() {
    var surfaceArea = 4 * Math.PI * Math.pow(this.radius, 2);
    console.log(surfaceArea + " square km!");
    return surfaceArea;
  }

  set gravity(value) {
    console.log("Setting value!");
    this._gravity = value;
  }

  get gravity() {
    console.log("Getting value!");
    return this._gravity;
  }
}

var earth = new Planet("Earth", 6378);
earth.gravity = 9.81;
earth.getSurfaceArea();

console.log(earth.gravity) // 9.81

That's all there is to it. One cool thing about adding these things to our class body is that they all will not live on the created object. They will live on the prototype (Planet.prototype) instead:

That is a good thing, for we don't want every object to unnecessarily carry around a copy of the class's internals when a shared instance would work just fine! Given that, you can see that represented in the above diagram. Our gravity getter and setter along with our getSurfaceArea function live entirely on our prototype!

Why do the functions inside my class look weird?

One thing you may have noticed is that the appearance of our functions inside the class body looks a bit odd. They are missing the function keyword, for example. That weirdness (for once) is actually not related to classes. When defining functions inside an object, you have a shorthand syntax you can use.

Instead of writing something like this:

var blah = {
  zorb: function() {
    // something interesting
  }
};		

You can abbreviate the zorb function definition as follows:

var blah = {
  zorb() {
    // something interesting
  }
};

It is this abbreviated form that you will see and use when specifying functions inside your class body.

Conclusion

The class syntax makes working with objects really easy. You may have caught some glimpses of that here, but you'll start to see more of it later on. The thing about the class syntax is that it allows you to focus more on what you want to do as opposed to fiddling with how exactly to do it. While working with Object.createand the prototype properties gave you a lot of control, that control was often unnecessary for majority of your cases. By working with classes, you trade complexity in favor of simplicity. That's not a bad thing when the simple solution also turns out to be the right one...most of the time!

If you have a question about this or any other topic, the easiest thing is to drop by our forums where a bunch of the friendliest people you'll ever run into will be happy to help you out!

THE KIRUPA NEWSLETTER

Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!

( View past issues for an idea of what you've been missing out on all this time! )

WHAT DO YOU THINK?

NEWSLETTER

No spam. No fluff. Just awesome content sent straight to your inbox!

Awesome and high-performance web hosting!
BACK TO TOP
new books - yay!!!