JavaScript may not be what comes to mind when someone mentions an OOP language, but the fact is it has great support for OOP - it just has its intricacies that need to be understood first. If you’re coding in JavaScript, getting familiar with OOP principles can make your life easier for a few reasons:
Here, you’ll learn the basics of Object-oriented JavaScript in ES5 and ES6 so that you can see the comparisons and how JavaScript has trended towards an OOP style.
Today we will cover:
Learn to write cleaner, more modular, and scalable code with OOP principles.
If you’re familiar with other languages such as C# and Java, then you’ve probably heard the term Object-Oriented Programming (OOP).
Object-oriented programming is a style of programming, not a tool, which is why even though it’s an older style, it’s still very popular and widely used. This style involves breaking a program into segments of objects that can communicate with each other.
Each object is defined by its own set of properties, which can then be accessed and modified through various operations.
The above illustration is a real-world example of an employee record where each employee can be considered an “object”, and since every employee has a name, age, and designation, these can be considered the properties of that employee.
OOP in JavaScript works differently than in other languages. So, if you’re familiar with OOP in other languages it’s important you put that knowledge aside for now since holding on to those concepts might confuse you.
You’ve probably seen that other languages such as C++, Java, and C#, use the keyword class to define a class. A class has properties and methods in it for every instance of that class. In this case, class acts as a blueprint for the object.
JavaScript differs from other languages because you can implement OOP without the use of classes (more on this later). Before introducing its ES2015 version, JavaScript still relied on prototype-based programming. In this programming style, the object encapsulates the properties, i.e., its methods and data, instead of a class.
You can add new properties to this object at any time. So now, an object can be an individual instead of being an instance of the class, meaning if you want an object you easily just create one without having to create a class first.
Both Prototype-based and Class-based OOP have their advantages and disadvantages. Prototype-based is more straightforward as you don’t need to create a blueprint beforehand which requires pre-planning about the sort of properties required before creating an object.
Since no class needs to be made, you can create the object directly. This also offers flexibility; hence, any changes to the objects can easily and quickly be made while they’re being used.
While all these advantages exist in Prototype-based programming, there is a higher risk of incorrectness as abrupt changes can easily be made. Whereas in the Class-based approach, the blueprints layout a plan beforehand, decreasing the chances of bugs arising.
Objects are a major part of JavaScript, as almost everything in it is an object. For example, functions, arrays, regular expressions, dates, and even data types like boolean and strings, if declared with the keyword new, can be considered a javascript object.
In real-life, objects are found everywhere, so these real-life scenarios can also be mapped into object-oriented code.
Let’s take a look at an example of how Objects are used. Assume you have three shapes which you need to find the area of: square, rectangle and circle. If you were to write code that would calculate the area of each, what would you do?
In an OOP style, you’d convert the code by creating objects for each shape: square, rectangle, and circle. Here, each object has its own set of properties which include:
We need the length, width, and the radius. These values will be encapsulated in the object of that particular shape. Similarly, a function to calculate the area will also be required. This will also be encapsulated in the object as a part of its properties.
An object literal can be created:
{...}
in the declaration.create()
method.All of these approaches do exactly the same thing. Here’s what the syntax looks like:
Using figure brackets
var objectName = {//properties definedpropertyName1 : propertyValue1,propertyName2 : propertyValue2,functionName() {}}
Using the new
keyword
var objectName = new Object()
Using the create()
method
var newObjectName = Object.create(existingObjectName)
Get: The get
keyword will bind an object property to a function. When this property is looked up now the getter function is called. The return value of the getter function determines which property is returned.
Set: The set
syntax binds an object property to a function to be called when there is an attempt to set that property.
This: The this
keyword refers to an object so that you can access the properties within an object. It can also be used to set the value of a property within an object.
Learn OOP concepts in JavaScript without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments, making learning quick and efficient.
There are various ways to access object properties. Outlined are a couple of popular ways, but you can also iterate over object properties using the for..in
loop and you can also access properties of a nested loop. To implement this all that is required is to use the dot operator, but you’ll need to add one additional dot.
The dot operator is also useful for setting and deleting properties. In JavaScript, an object literal can be accessed using the dot operator. To access any property, the name of the object should be mentioned first, followed by the dot operator, and then the name of the property encapsulated in that object.
Here we can see the syntax of the dot operator:
objectName.functionName()
Here’s an example of how to access properties using the dot operator:
Here’s an example of how to access properties using the dot operator://creating an object named shapevar shape = {//defining properties of the object//setting data valuesname : 'square',sides : 4}//accessing the properties using the dot operatorconsole.log("Name is:", shape.name) //using dot operator to access "name"console.log("Number of sides are:", shape.sides) //using dot operator to access "sides
Another method to access values is by using the square brackets [ ]
. The name of the property to be accessed is written inside the square brackets as a string. Using square brackets is also useful for setting and deleting properties.
Here we can see the syntax of the square brackets method:
objectName['functionName']()
Here’s an example of how to access properties using square brackets:
//creating an object named shapevar shape = {//defining properties of the object//setting data valuesname : 'square',sides : 4}//accessing the properties using square bracketsconsole.log("Name is:", shape['name']) // to access "name"console.log("Number of sides are:", shape['sides']) // to access "sides"
Functions are also objects in JavaScript. This is because just like objects, they have their own properties and methods. Functions can be used to construct objects as well, and these types of functions are known as constructor functions.
Constructor functions essentially eliminate the need to create separate object literals for similar tasks. They are useful because you’ll often come across situations in which you don’t know how many objects you will be creating; constructors provide the means to create as many objects as you need in an effective way.
Here is the syntax for implementing the constructor function:
function FunctionName(parameter1, parameter2,...){//all the properties of the object are initialized here//functions to be provided by objects are defined here}
As can be seen from above:
Here is an example of a constructor function:
function Employee(_name, _age, _designation){this.name = _namethis.age = _agethis.designation = _designation}
Note that all the objects created from Employee
will contain the properties name, age, and designation, where the keyword this
can assign specific values even though they’re part of the same property.
Prototype objects are a simpler approach for adding new methods/properties to a constructor function.
Aside from the properties that you create, there is an additional hidden property known as [[Prototype]]
property that is present inside every object created from a constructor function. The prototype property either points to another object or is null. Here is an example of using the Prototype property:
//Shape objectvar Shape={name: 'Rectangle',sides: 4}//Rectangle objectvar Rectangle = {length: 3,width: 5}//setting [[Prototype]] of Rectangle equal to ShapeRectangle.__proto__ = Shape//creating an object instance using Shape and Rectangleconsole.log("Name of shape is:",Rectangle.name)console.log("Number of sides are",Rectangle.sides)console.log("Length is:",Rectangle.length)console.log("Width is:",Rectangle.width)
Here we can see that when the prototype property of Rectangle is set to Shape, it is able to access all the properties in Shape. If a property is not found in the object, such as the name
property is not found in Rectangle, JavaScript will automatically take it from the prototype of that object, Shape. This is known as prototypal inheritance where lines 20 and 21, are known as inherited properties; this is based on the concept of prototype chaining.
JavaScript ES6 offers some new features as well as improvements. One of those improvements that is the introduction of the keyword class. You can explore all the other nuances of ES6 here
Whereas in JavaScript ES5, function constructors were used to implement the concept of classes. However, in the ES6 version, the class
keyword is used which cleans up the syntax for implementing the same concept, making it easier to understand.
The syntax is as follows:
class ClassName {constructor() {//initializing class properties}//class methods defined}
One of the differences between the constructor function and class-based implementation is that, in the former, the body of the function acts as the constructor, where all the properties are defined, whereas, in the latter, there is a separate constructor function defined inside the class used to initialize the properties.
Here we can see an example of how to create an object instance from a class:
//creating a class named employeeclass employee{//creating the constructor functionconstructor(name,age,designation){//all properties defined as they were in the constructor functionthis.name = namethis.age = agethis.designation = designationthis.displayName = function() {console.log("Name is:",this.name)}}}//creating an object instance named "employeeObj"var employeeObj = new employee('Joe',22,'Developer')//displaying the properties of employeeObjemployeeObj.displayName()console.log("Age is",employeeObj.age)console.log("Designation is:",employeeObj.designation)
Since employee
is a constructor function itself, the method to create an object instance from a class is exactly the same as that in the ES5 version. The new
keyword is used to initialize a new object, employeeObj
. The constructor
method then runs for this object assigning the values passed into it to the properties.
Whenever a method is declared inside a class, it is defined on the prototype of that class. Meaning, whenever an object instance accesses it, it gets taken from the respective class’s prototype.
Here is an example:
//creating a class named employeeclass employee{//creating the constructor functionconstructor(name,age,designation){//all properties defined as they were in the constructor functionthis.name = namethis.age = agethis.designation = designationthis.displayName = function() {console.log("Name is:",this.name)}}//defining methods in a class//getAge method returning the age of the current objectgetAge(){return this.age}}
Here’s what’s happening in the code above:
getAge
function is being defined outside of constructor function in line 15.employeeObj
, has access to all the methods defined in the class.employeeObj
the method getAge
is taken from employee.prototype.Although JavaScript may not be considered an OOP language, the use of version ES6 (because of the use of classes) will give you a feel of what it’s like to code in a more traditional OOP programming language such as C/C++. The major differences between ES5 and ES6 is the addition and clean-up of syntaxes.
There is much more to learn, such as:
If you’re interested in going into more detail, you can learn all the essentials with Learn OOP in JavaScript. You’ll build up to more advanced concepts such as prototypal inheritance, prototype chaining, method overriding, and mixins.
Free Resources