Understanding Data Structures: Class Syntax in Javascript

In previous blog posts, I’ve gone over different Data Structures as a way to deepen my understanding of these concepts for myself. At the time and currently I still consider myself a novice when it comes to understanding data structures fully, I know many by name and few by experience. In this blog post I will be exploring classes in Javascript. JS isn’t formally an Object Oriented Language, but it is one of my favorite languages so I will be continuing my learning and delving into Data Structures within the context of this language. I’ve had to step away and come back multiple times. I have found taking breaks and stepping away helpful in regards to building my skills and hopefully, in writing this, I can be of help by passing on what I know.

Photo by Alexandar Todov on Unsplash

Before moving forward this will involve object oriented programming or OOP and if you don’t know what that is, firstly that is ok. Second, Javascript is not an object oriented language but there are ways we can use JavaScript to behave like one. Lastly, there are 4 pillars to object oriented programming (OOP).

1. Encapsulation
2. Abstraction
3. Inheritance
4. Polymorphism

I will go more in depth in the 4 pillars above as we continue.

What is a class?

A class is like a blueprint or template for creating objects, or it can be compared to a factory that produces objects. These objects will have pre-defined properties and methods. Data Structures are implemented as classes. So in the future as I cover other Data Structures as future topics, we will be using classes to declare or define them.

Declaring a class is simple. The keyword class creates a constant, and the class is always written in Camel case, meaning it starts with a capital letter. Inside this class constant, we use the constructor method and pass in parameters. Inside the constructor method, we define the parameters using the this keyword to indicate that we are referring to the class constant, followed by a dot notation for the parameter.

So for example:

class Person{
constructor(name, age) {
this.name = name;
this.age = age;
}
}

So if we were to create a new person object with a name of Billy who is 19 years old, Billy would be instantiated as a Person class, with the this.name “Billy” and the this.age of 19. This in the context of a constructor is referring to the Person class. So whatever instance of a Person we create in the future, this will be referring to that specific instance of the object being created. And to instantiate a new object we do it like so:

let firstPerson = new Person("Billy", 19) 

If we were to type firstPerson.name (again, to point out, firstPerson.name is assigned by this.name in the constructor) into a console.log, we would return “Billy”. The class of Person is like a pattern that we can use again and again. We can create new instances of Person. The new Persons when created will have a name value and an age value, different people but all able to inherit from this class, Person.

Is a method that we use on an instance of a class. So in the above example, a Person can do something like goToBed(), it’s a behavior, and when invoked, just that one person goes to bed. Another example that’s more familiar is with an array. Let’s say we create a new array called People. People.push() is an example of using an instance method on the Array called People. We are using the instance method .push on a specific array and adding something to the end of the array called People, and just that array. All array’s can use the built in .push method. And for our example, all Persons created can use the method goToBed().

class Person {
constructor(name, age){
this.name = name;
this.age = age;
}
goToBed(){
return `${this.name} is going to bed.`;
}
}
let firstPerson = new Person("Billy", 19)
let secondPerson = new Person("Jessie", 23)
console.log(secondPerson.goToBed())
//=> "Jessie is going to bed."

As we begin creating instance methods, we can begin altering the state of our objects. Encapsulation in OOP is when each object maintains a private state, meaning we are able to interact with our data as unique objects. Another way to look at this: firstPerson is unique from secondPerson and they have unique data encapsulated within them.

A simple way to think of abstraction is that we are calling on the unique and specific sets of data. We abstract when we use the dot notation to get specific data. Right now our Person class is pretty simple, but if we were build out the Person class to contain more data, like an online user, in order to pull specific data from a Person’s profile, we could specifically ask for the this.username to access only the username of the instance of our Person class. The process of selecting/fetching/removing specific data from within an object is Abstraction and it builds off of Encapsulation.

I used the word inheritance when referring to a Person object; when a Person is instantiated they would have a name parameter and an age parameter, and they would have access to the goToBed() instance method. Let’s say we create a new class called Teacher. And let’s say we wanted a Teacher to inherit from the person class. A Teacher class that inherits from the Person Class would look like:

Class Teacher extends Person{
constructor (name, age, course) {
super(name, age)
this.course = course
}
intro(){
`Hello class, welcome to ${course}!`
}
}

Teacher is a type of Person and so in the example above it is inheriting the methods and properties of the Person class or in other words its parent class.

To reiterate, the Teacher class is a child of the Person class. Or another way of looking at it, is that Teacher is a Person, but it has its own unique properties. Let’s say we have another class called Student. A Student is also a Person, but is not a Teacher and therefor has access to unique properties compared to that of a Teacher. Now let’s create a new property inside of Person called privateContainer. Both a Teacher and a Student can inherit this privateContainer from the Person class but the expression of this property will be different. An instantiated Teacher will have an office, and a student would have a locker. They both are inheriting the same property, but it’s expression is different and that is polymorphism.

Class methods we create inside of the class but it can only be used on the class itself and not on the instance of a class. And we do this using the keyword static like so:

Class Student extends Person{
constructor (name, age, grade) {
super(name, age)
this.grade = grade
}
static pair(a,b){
return `${a.name} and ${b.name} will be partners`
}
}
let firstStudent = new Student("James", 24, 4)
let secondStudent = new Student("Archie", 26, 3)
Student.pair(firstStudent, secondStudent)
//=> "James and Archie will be partners"

On it’s own, I didn’t really understand why classes would be useful, but as I’ve been getting into Data Structures, the use cases for classes have been fundamental to my learning. I hope this guide serves as a helpful introduction or resource as you begin learning about data structures.

A Software Engineer with a background in Education Technology and Dance. Recent grad form FlatIron Bootcamp, and passion for the arts and working with databases

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store