Classes

Before we start discussing Classes in JavaScript, one thing needs to be explained. Classes in JavaScript are more like syntatic sugar than the new feature. Nevertheless, as in the case of Arrow Function about which I wrote in the previous section, this is a facility worth remembering.

JavaScript does not really have class inheritance, but something called prototypal inheritence. Class inheritence has been introduced to JavaScript due to the fact that it occurs in the vast majority of programming languages. So what are Classes in JavaScript except for syntatic sugar, which leads to a more readable syntax? The answer is simple and the same as in other object-oriented programming languages. They are to create objects. They are like blueprints, on the basis of which objects are created. In addition, JavaScript classes are basically special functions. The class declaration consists of two parts. The expression class and class declaration. Example below.

class Dog {

}

Nothing complicated. But now let's look at what will happen as in the console type of Dog.

Exactly as I mentioned. Our class is a function on the basis of which we will later create objects.

There are still a few things missing in our Dog class. The first one will be a Constructor. This is a special keyword used to initialize the object data. Constructor can accept any number of parameters. In our example, we will create two, name and height, and then using variable this we will ensure that the arguments passed in the parameters will be saved in the variables. In our case, also with the same names. Of course, it is possible to name the classy property differently than the parameter, as in the example below, however, it is not very legible and not recommended.

class Dog {
  constructor(name,height) {
    this.hellothere = name;
    this.randomstuff = height;
  }
}

let Staffie = new Dog("Bur",100);

But let's return to normal way of doing things.

class Dog {
  constructor(name,height) {
    this.name = name;
    this.height = height;
  }
}

Once we have a created class, we can boldly create any number of objects / instances of this class. The way we do it, is as follows.

let Staffie = new Dog("Bur", 60);

The name of our object in this example will be Staffie. Next, we pass to parameters that we defined in the constructor two arguments. The first "Bur" will be our name, the second 60 will be the height.

In addition, we can create methods in classes. The method is really just a function that is placed inside the class. So let's add a method that will return the sound of barking.

class Dog {
  constructor(name,height) {
    this.name = name;
    this.height = height;
  }
  barking() {
    return "wuff wuff";
  }
}

let Staffie = new Dog("Bur", 60);

Now our Staffie has the option of using this method. When we call the barking method in the console, we get:

Since we know how to create classes, let's look at the inheritance. Since the dogs are divided not only by races, but also groups, let's create a Terrier class that will inherit from the Dog class. It is also not complicated.

class Dog {
  constructor(name,height) {
    this.name = name;
    this.height = height;
  }
  barking() {
    return "wuff wuff";
  }
}

let Staffie = new Dog("Bur", 60);

class Terrier extends Dog {
  constructor(name,height,color) {
    super(name,height);
    this.color = color;
  }
}

let Bullterrier = new Terrier("Tommy", 30, "white");

In the above example, we see that in order to be able to inherit from another class, we use the word extends + the name of the class from which we want to inherit. In addition, we see keyword super. It is used to allow us using the special variable this and have access when creating an instance of the Terrier class to the name and height parameters which are inherited from Dog class.

Another thing is that is often encountered is, when we want to use our method barking in the case of Terriers, however, returned value would be something different than in a regular dog.

class Dog {
  constructor(name,height) {
    this.name = name;
    this.height = height;
  }
  barking() {
    return "wuff wuff";
  }
}

let Staffie = new Dog("Bur", 60);

class Terrier extends Dog {
  constructor(name,height,color) {
    super(name,height);
    this.color = color;
  }
  barking() {
    return "WUFFFF WUFFFF";
  }
}

let Bullterrier = new Terrier("Tommy", 30, "white");

As you can see, there is no magic in it. Now our terrier Tommy will be barking in a way that any self-respecting terrier does.

Generally, convention from languages like Java in which there is an object-oriented programming model also assumes holding classes in different files. Namely, instead of just like in our example one file with two classes, a better solution would be to transfer them to two separate files. Thanks to such a procedure, our code would become much more readable which is a great advantage when writing.

Dog class

class Dog {
  constructor(name,height) {
    this.name = name;
    this.height = height;
  }
  barking() {
    return "wuff wuff";
  }
}

export default Dog;

Terrier class

import Dog from "./Dog";

class Terrier extends Dog {
  constructor(name,height,color) {
    super(name,height);
    this.color = color;
  }
  barking() {
    return "WUFFFF WUFFFF";
  }
}

As you can see we used two keywords. Import and Export. As you probably already figured out what they are used for. I will only mention that you can export functions, objects, or primitive values from the module so they can be used by other programs with the import statement.

Another topic worth mentioning in this part is the static methods. So what are they exactly? First of all, they are created with a keyword static. Most important thing about them is that they are called directly on the class and are not callable on an instance of the class. Their purpose is to create a utility function.

class Dog {
  barking() {
    console.log("wuff wuff");
  }
  static grr() {
    console.log("grrr");
  }
}

let Staffie = new Dog();

We created an instance of Dog class and named it Staffie once again. Let's try to invoke both methods.

Ok, the method barking works as intended. Now let's invoke second one.

As you can see it works as intended too. We can't invoke a static function on the object. On another hand is it possible to invoke it on the class as its supposed to ?

Great, it does.

So, did JavaScript after the introduction of the ES6 standard start to belong to languages that use the Object-Oriented Programming (OOP) model? The answer, it does not. JavaScript is still based on the Prototypal inheritance model.

Next Post

We'll talk about rest & spread.