Sure, classes are an object-oriented programming concept you will certainly come across while coding. JavaScript classes however, work a bit differently.
In this article, we’ll cover how classes are different in JS under the hood, and go over how to write a simple class, step by step.
At the same time, we’ll learn about key approaches like prototypical inheritance, which is key to using JavaScript classes.
Feel free to jump to a specific section via clicking one of the headings below:
- What is JavaScript?
- What are JavaScript classes for?
- Prototypical inheritance and prototype chaining
- How to create JavaScript classes
- Final thoughts
1. What is JavaScript?
Javascript is a programming language that makes up the basis of the world-wide web, together with HTML and CSS. All major web browsers have an engine to interpret JavaScript, and an impressive 98% of web pages online are written in the language.
If you’d like to learn more about this language, we’ve created a full introductory guide to JavaScript. Prefer to get stuck into learning it instead? Then allow Abhishek to show you in this video tutorial:
Regardless of how familiar with it you are, what’s important to remember her is that JavaScript is a multi-paradigm programming language. This includes functional, object-oriented, and prototypal programming.
2. What are JavaScript classes for?
A class is a template for creating objects. It encapsulates data and functions that manipulate data, grouping data and functionality together.
Classes are based on object-oriented programming concepts. As JavaScript is not an object-oriented programming language at its core, JavaScript classes are considered syntactic sugar.
Wait—sugar what?!
What this means is classes are there as a visual aid in Javascript. They were introduced in EcmaScript2015 (ES6) to allow developers to follow object-oriented programming patterns in a cleaner way. It’s just one of the many reasons that ES6 is so great.
We consider this “syntactic sugar” as it makes things easier to read, i.e. “sweeter” for human use. In this case, for developers who prefer object-oriented programming.
3. Prototypical inheritance and prototype chaining
Classes and object-oriented programming (OOP) are unique in JavaScript as they use prototypical inheritance under the hood.
This is compared with other object-oriented programming languages like Java and C++, which use classical inheritance. In classical inheritance, classes can inherit from classes and create subclasses.
The downside of this is that it’s quite verbose and can end up in huge trees of objects that are interacting with each other. When this happens it’s easy to lose track of what’s going on.
Prototypical inheritance is a simpler approach focused on objects inheriting from objects. Let’s take a look at what inheritance looks like in Javascript.
Inheritance
Inheritance is when one object gets access to the properties and methods of another object. Below we will create two objects, Animal and Cat. We’ll set the prototype of Cat to Animal.
const Animal = {
name: 'Oscar',
age: 4,
numberOfLegs: 2,
sound: () => console.log('rawr'),
};
const Cat = {
name: 'Loki',
age: 7,
numberOfLegs: 4,
};
Object.setPrototypeOf(Cat, Animal);
console.log(Cat);
If we log this, we’ll see:
You can see when we log the Cat object, it gets a Prototype field, which is set to the Animal object. Make note that the Animal object has a method sound, and the Cat object does not. What happens if we log Cat.sound()?
console.log(Cat.sound()) // rawr
Since Cat’s prototype is Animal, it has access to the properties and methods from Animal. Since Cat doesn’t have its own sound method, it will use Animal’s and log ‘rawr’. This is an example of inheritance.
Prototypes and prototype chains
In JavaScript classes, every object has a built-in property called a prototype. This prototype is an object with its own prototype, which creates the prototype chain. When we reach a prototype equal to null, the chain ends.
The reason why our Cat object has access to Animal’s sound method is due to this prototype chain. First, JavaScript tries to access the properties and methods in the current object.
If it’s not there, it goes up to its prototype and looks there. If still no luck, it looks at THAT object’s prototype, etc. If we hadn’t found sound before reaching the end of the prototype chain, the value would return undefined.
4. How to create JavaScript classes
Now that you understand the basics of prototypical inheritance in JavaScript, let’s take a look at the class syntax. Again, JavaScript classes are syntactic sugar over the prototypical inheritance model. The introduction of class syntax makes it easier for developers to build software using OOP concepts. Here is an example of a class:
class Person {
constructor(name, age, hairColor){
this.name = name;
this.age = age;
this.hairColor = hairColor; this.sayName = () => ‘My name is’ + this.name;
}
}
const anna = new Person(‘Anna’, 37, ‘red’);
anna.sayName(); // My name is Anna
To create a class, you use the class keyword. Within the class, we create a constructor function, which defines all the initial properties.
Different from our objects above, a class is a template for creating objects. All the properties in the constructor function will be automatically added to your new object.
Let’s see what happens when we log our new object, anna:
You can see we created an anna object using our class, with the properties age, hairColor, name, and sayName() that were defined by our Person class’s constructor function. You can also see the prototype of our anna object is the object instance of our Person class. This means it’s an object containing data and behavior described by the class.
The new keyword
Our new variable anna is also using the new keyword. When a function is called with the new keyword, it does the following:
- Creates a new blank JavaScript object
- Points our new object’s prototype to the constructor function’s prototype property (i.e. Person)
- Runs Person’s constructor function with the given arguments (name, age, hairColor)
Classes can only be used to create new objects with the new keyword. If you call a class without new, it will throw a TypeError.
Extending a class with extends keyword
We mentioned how the class syntax makes creating objects cleaner. Let’s take a look at an example of that. While we’re making People objects, we realize there are some subcategories of people that have their own properties.
Let’s consider Teacher in this example:
class Teacher extends Person {
constructor(name, subject, salary){ super(name)
this.subject = subject;
this.salary = salary;
}
doGrading(){
console.log('You get an A+ in ' + this.subject);
}
}
const myTeacher = new Teacher('Mark', ‘history’, ‘60,000€’);console.log(myTeacher.subject); // history
myTeacher.sayName(); // My name is Mark
Our Teacher inherits the methods of our Person class by using the extends keyword. It also has some unique properties of its own, like subject, salary, and the method doGrading().
The super keyword
You see how we were able to access the sayName() method even though we didn’t define it in our Teacher class? You can imagine this saves a lot of space when there are many properties and methods involved.
Adding the super() method in Teacher’s constructor function calls Person’s constructor method and gets access to its properties and methods. In this case we add name as an argument as we want to access that in Teacher.
Final thoughts
JavaScript classes and object-oriented programming are complex topics in themselves, so it’s okay if you don’t fully understand all the details yet.
Now you know how to write a simple class, and what super, new and extends do.
You’ve learned a bit about why someone would use JavaScript classes, and how they work a bit differently under the hood in Javascript than in OOP languages due to how the language handles inheritance via the prototype chain.
To learn more about object-oriented programming and JavaScript in general, you can check out these articles: