JavaScript ES6 for Beginners #8: Classes
Quoting MDN:
classes are primarily syntactical sugar over js’s existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
That being said, let’s review prototypal inheritance before we jump into classes.
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function(){
console.log("Hello, my name is " + this.name);
}
const alberto = new Person("Alberto", 25);
const caroline = new Person("Caroline",25);
alberto.greet();
// Hello, my name is Alberto
caroline.greet();
// Hello, my name is Caroline
We added a new method to the prototype in order to make it accessible to all the new instances of Person that we created.
Ok, now that I refreshed your knowledge of prototypal inheritance, let’s have a look at classes.
Create a Class
There are two way of creating a class:
- class declaration
- class expression
// class declaration
class Person {
}
// class expression
const person = class Person {
}
Remember: class declaration (and expression) are not hoisted which means that unless you want to get a ReferenceError you need to declare your class before you access it.
Let’s start creating our first Class
.
We only need a method called constructor
(remember to add only one constructor, a SyntaxError
will be thrown if the class contains more than one constructor methods).
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
greet(){
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old` );
} // no commas in between methods
farewell(){
console.log("goodbye friend");
}
}
const alberto = new Person("Alberto",25);
alberto.greet();
// Hello, my name is Alberto and I am 25 years old
alberto.farewell();
// goodbye friend
As you can see everything works just like before. As we mentioned at the beginning, Classes are just a syntactical sugar, a nicer way of doing inheritance.
Static methods
Right now the two new methods that we created, greet()
and farewell()
can be accessed by every new instance of Person
, but what if we want a method that can only be accessed by the class itself, similarly to Array.of()
for arrays?
static info(){
console.log("I am a Person class, nice to meet you");
}
alberto.info();
// TypeError: alberto.info is not a function
Person.info();
// I am a Person class, nice to meet you
set
and get
We use setter and getter methods to set and get values inside our Class
.
class Person {
constructor(name,surname) {
this.name = name;
this.surname = surname;
this.nickname = "";
}
set nicknames(value){
this.nickname = value;
}
get nicknames(){
return `Your nickname is ${this.nickname}`;
}
}
const alberto = new Person("Alberto","Montalesi");
// first we call the setter
alberto.nicknames = "Albi";
// "Albi"
// then we call the getter
alberto.nicknames;
// "Your nickname is Albi"
Extending our Class
What if we want to have a new Class
that inherits from our previous one? We use extends
:
// our initial class
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
greet(){
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old` );
}
}
// our new class
class Adult extends Person {
constructor(name,age,work){
this.name = name;
this.age = age;
this.work = work;
}
}
const alberto = new Adult("Alberto",25,"teacher");
We created a new Class Adult
that inherits from Person
but if you try to run this code you will get an error:
ReferenceError: must call super constructor before using |this| in Adult class constructor
The error message tells us to call super()
before using this
in our new Class
.
What it means is that we basically have to create a new Person before we create a new Adult and the super()
constructor will do exactly that.
class Adult extends Person {
constructor(name,age,work){
super(name,age);
this.work = work;
}
}
Why did we set super(name,age)
? Because our Adult
class inherits name and age from the Person
therefore we don’t need to redeclare them.
Super will simply create a new Person for us.
If we now run the code again we will get this:
alberto.age
// 25
alberto.work
// "teacher"
alberto.greet();
// Hello, my name is Alberto and I am 25 years old
As you can see our Adult
inherited all the properties and methods from the Person
class.
Extending Arrays
We want to create something like this, something similar to an array where the first value is a property to define our Classroom and the rest are our students and their marks.
// we create a new Classroom
const myClass = new Classroom('1A',
{name: "Tim", mark: 6},
{name: "Tom", mark: 3},
{name: "Jim", mark: 8},
{name: "Jon", mark: 10},
);
What we can do is create a new Class
that extends the array.
class Classroom extends Array {
// we use rest operator to grab all the students
constructor(name, ...students){
// we use spread to place all the students in the array individually otherwise we would push an array into an array
super(...students);
this.name = name;
// we create a new method to add students
} add(student){
this.push(student);
}
}
const myClass = new Classroom('1A',
{name: "Tim", mark: 6},
{name: "Tom", mark: 3},
{name: "Jim", mark: 8},
{name: "Jon", mark: 10},
);
// now we can call
myClass.add({name: "Timmy", mark:7});
myClass[4];
// Object { name: "Timmy", mark: 7 }
// we can also loop over with for of
for(const student of myClass) {
console.log(student);
}
// Object { name: "Tim", grade: 6 }
// Object { name: "Tom", grade: 3 }
// Object { name: "Jim", grade: 8 }
// Object { name: "Jon", grade: 10 }
// Object { name: "Timmy", grade: 7 }
This was the eigth part of my ES6 for beginners course, check out the rest of them here.
You can also read this articles on medium, on my profile.
Thank you for reading.
Leave a Comment