Object-oriented programming in JavaScript #1. Abstraction.
Fast growing of internet performance is raising expectations and requirements for the web applications. New complexities and tasks are more often solved in frontend by JavaScript. Same as the usage of Node.js in backend, UI requires complex solutions using the latest trends in programming. Object-oriented programming (OOP) has been one of the fundamental paradigms for last decades. That’s why I think it is really important to have a good knowledge of it for frontend developers as well.
Let’s see how Wikipedia defines it.
“Object-oriented programming is a programming paradigm based on the concept of “objects”, which may contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods.”
The main thing for us here is the concept of “objects”, while the second part just describes its properties.
So, let’s consider in details OOP principles, which are Abstraction, Inheritance, Polymorphism and Encapsulation.
Abstraction is a way of creating a simple model of a more complex real-world entities, which contains the only important properties from the perspective of the context of an application.
Abstraction manages complexity of a system by hiding internal details and composing it in several smaller systems.
The main idea of abstraction is to define real-life components in different complex data types. In most OOP languages it is implemented with class keyword, so basic understanding of it can be something like a custom data type. More deeply, class is an implementation of a concrete data structure with functionality implemented in methods.
Class is like a template for creating multiple objects with same list of properties but different data values saved in it.
In ES2015 specification of JavaScript keywords class and extends were provided, which gives us an ability to use OOP in a common way with the other programming languages like Java, C#, Python.
We won’t dive deeply in syntax features of the latest specifications, you can find enough information about it in different videos and articles.
Code examples from this article will work in Chrome and Node.js. There is an option to transpile our code using one of the JS compiler such as Babel, to be able to run it in older browsers. So do not worry much about browser support of new code syntax features.
Let’s look into the parts of JavaScript class which defines complex data structures.
First of all we have a constructor method which is executed when we initialize a new instance, inside of it we can add some new properties to object. Here we have access for the arguments init1
and init2
that helps us to set initial state of the newly created object.
Get/set accessors provide abilities to create computed properties based on object state or add validation for setting property values.
Methods provide an interface for communication between objects and behavioral functionality that may be executed from context of creating an object.
Some general data and functionality which are related to class, but not to a concrete instance should be implemented in static methods. Those are accessible on class but not on concrete instance.
Let’s consider an example. We need a list of people in scope of our application, and we need to know their first and last name, skills, their job and salary, but in the same time we don’t need the age, height, weight, we can just skip it.
On the left side we have real-life entities: Person and Job. In the middle you can see programming abstraction with the only needed properties in our application. The instances of class that represents concrete people and jobs are shown in circles on the right side of the image.
Here, we have an illustration of abstraction in managing complex data structure Person, details of property “job” are hidden in smaller Job class to keep code clean and structured. Abstraction helps to define the core of the context of an application.
Object instantiated from the class contains the data values and the functionality defined in the class.
For a constructor, we have used unpacking fields from object argument passed as a function parameter. Inside of a constructor method we are setting an initial state (based on the arguments) of a new class instance appending properties to this. Person._amount
is the simulation of a private static property. We use that to provide the functionality for tracking amount of Person objects instantiated inside the application.
Prefix ‘_’ is often used as a convention for private properties in JavaScript as there are no private members in current ES2018 specification. But there is already a proposal on Stage 3 (at the moment of publication) which will provide abilities to use a private member in JS class.
Static getter amount
is used for retrieving private _amount
of instantiated objects, and is available to be executed on classPerson.amount
, but not on instance(viktor.amount === undefiend
).
Getterget fullName
returns computed String value based on the instance firstName
and lastName
properties values.
Setter set fullName
is used for updating firstName
andlastName
properties, inside of it we’ve added validation for string value which should have characters separated by space.
Method learn
provides functionality that extends skills array of a concrete person.
We’ve created 2 instances john
and roger
, executed methods and properties on it.
Abstraction is an important and a fundamental principle in OOP. It is based on creating custom data structures, classes. The current version of JavaScript already has a mechanism that provides the ability to create and work with classes in common way to other popular OOP languages. Also it will be even extended soon by new proposals for example proposal-class-fields.
In the next article we are talking about Inheritance.