OOP

Is JavaScript An Object-Oriented Programming Language?

In JavaScript by Rune

JavaScript is no doubt one of the most popular programming languages today as it is used almost everywhere.

Looking at the reception JavaScript received from developers since its creation, it has clearly been the focus of a lot of controversies. Today, we would look at one of such controversies.

Is JavaScript an object-oriented programming language?

There has been a lot of debate on this issue. This same issue has caused a lot of developers to have negative opinions on the language in general. However, JavaScript is known to be a misunderstood language as it defies a lot of programming language design patterns.

The short answer to the question is, yes.

Yes, JavaScript is an object-oriented programming language. Almost everything in JavaScript is an object. You can also implement the main concepts of object-oriented programming which are encapsulation, inheritance, and polymorphism using JavaScript. Therefore, JavaScript is an object-oriented programming language.

In this article, we are going to break things down as much as possible. We would take a look at the major object-oriented programming concepts, the reasons why developers think it is object-oriented or otherwise and we would also compare JavaScript to another language such as Java in terms of object-oriented programming concepts.

What is Object-Oriented Programming?

This is the best way to kick things off. A lot of developers get things wrong from the understanding of the basic concepts and that would have a ripple effect on their understanding of other things.

According to Wikipedia, Object-oriented programming can be defined to be:

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.

Wikipedia

In simpler terms, object-oriented programming is based on the idea that software can be written in terms of objects. This is contrary to what we find with functional programming where software is written in terms of actions (functions or procedures).

Every object can be described using their characteristics, and objects can also take certain actions. Object-oriented programming takes advantage of this to ensure software is built with a clear thought process. Besides, since we are building software to solve the world’s problems, it is only logical to model things in the software just like we have in the real world.

Taking a look at a door for example. A door would have a certain height, width, color, hinge type. A door can also open in certain directions and close too. Thinking of the door in this manner makes it easier to build software that models the door.

Remember the talk of software having characteristics and actions? In object-oriented programming, the characteristics are called attributes and the actions are called methods—what we call functions in functional programming.

This raises a question: Why resort to object-oriented programming if we could just stick to functions only and manipulate variables?

Well, with object-oriented programming, the attributes are a key part of objects and the methods are created to manipulate the object’s attributes.

Before we proceed, let’s take a look at something that makes object-oriented programming powerful.

Classes

Classes are like blueprints that allow us to create objects in many places. Taking a look at the door example, we could create a mold for a door—the class is the mold in this case—and create as many doors as possible using the same configurations and no stress.

Let’s look at the four concepts that make object-oriented programming very powerful. They are abstraction, encapsulation, inheritance, and polymorphism.

Abstraction:

Abstraction is an important engineering concept. For the world to work, abstraction is key. Using the door analogy, you do not need to know how the wood or metal—depending on what type of door—the door is made off was gotten before you use the door. You do not need to know how the hinges were made before you use the door.

Everything is an abstraction. The same applies in your code, you can use objects without having to know how they were created.

Inheritance:

Inheritance works as expected. You can create objects to inherit certain attributes (characteristics) from other objects. Thanks to inheritance, you do not need to create objects from scratch.

Therefore, if you have two doors and you want certain attributes from them you can simply inherit them. This is just as found with humans, a child would inherit characteristics from the parents.

A parent class is known as a superclass and a child class is known as a subclass. With inheritance, you can decide to change certain methods and properties by overriding them and giving them appropriate new values.

Polymorphism:

Polymorphism is based on the concept that one method can be performed on various objects and they would execute different actions.

While the door analogy would not be good in this case, we could use an animal analogy. The Dog and the Cat are both animals, however, they make different sounds.

Therefore, if we create an object and use a “make_sound” method on both of them, one would sound “Woof!” and the other “Meew!”, the sound is dependent on the object in focus.

Encapsulation:

Encapsulation and abstraction work hand in hand. Encapsulation also helps keep certain details away from the user by hiding attributes and allowing only some methods to manipulate those attributes.

Using a bomb analogy here: a bomb could have an explode attribute. This attribute is one which is very critical, therefore you would not allow just any access to this attribute. To manipulate the attribute, you could only allow a method access to it, possibly a method that would set a timer before allowing an explosion.

Therefore, you are not able to alter certain attributes without using certain methods. In object-oriented programming, those methods are known as getters and setters.

Common arguments why JavaScript is Object-Oriented

There are arguments to why JavaScript is object-oriented, let’s look at some of them.

Almost everything In JavaScript is an object:

For a language to be object-oriented, it needs to be able to deal with objects—create, instantiate, manipulate etc.

JavaScript has two built-in types. The primitive types and the reference types.

The primitive types include strings, booleans, integers etc. and the reference types are objects, some of which are functions, regex, collections such as set. Every reference type in JavaScript is an object.

This is one reason why developers argue that JavaScript is indeed object oriented.

It can implement the four major OOP ideas:

A programming language is not object-oriented if the major concepts of object-oriented programming cannot be implemented. With JavaScript, you can implement encapsulation, inheritance, and polymorphism—abstraction is more of a design concept than an implementation concept.

These two points should be more than enough reason to accept that JavaScript is an object-oriented programming language.

Common arguments why JavaScript is NOT Object-Oriented

While the points stated earlier for JavaScript being an object-oriented programming language are great, there are certain points to counter them.

JavaScript doesn’t have classes:

Object-oriented programming languages are either class-based or prototype-based. Some developers believe that since objects are not created using classes in JavaScript, then it is not an object-oriented programming language.

JavaScript doesn’t provide direct inheritance:

JavaScript does not provide direct inheritance as seen in other programming languages, however, it can be worked around. The issue of direct inheritance is one other reason why some developers believe that the programming language is not object-oriented.

As we proceed in this article, we would see how these points have been tackled in recent versions of JavaScript.

How does JavaScript differ from other programming languages regarding OOP?

Unlike JavaScript, languages such as Java and C# do not have issues with the concept of object-oriented programming. This is because all—or almost all—developers consider them to be complete object-oriented programming languages.

Here, we are going to be comparing JavaScript and Java through three of the four major parts of object-oriented programming—encapsulation, inheritance, polymorphism.

Encapsulation:

In Java, C#, the private attributes, getters, and setters are all created in the classes before instantiating them. It is different with JavaScript though, as the objects have to be instantiated through a variable and then the getters and setters are added using the created variable.

Inheritance:

While a language such as Java uses class-based inheritance, JavaScript uses prototype-based inheritance.

Inheritance in Java is as easy as using the extends keyword, however, with JavaScript this is done by assigning an object as a prototype using a constructor function.

Class-based inheritance basically means the copying or inheritance happens at compile level. However, with prototype-based inheritance, the copying happens at runtime.

Polymorphism:

Polymorphism doesn’t work as expected on JavaScript the way it runs on Java and C#.

Unlike in programming languages such as Java and C#, all the methods to be added and overridden need to be done while creating the object. However, with JavaScript, things are different as methods can be added and overridden on the fly after creating the objects.

All of these difference have been worked on in the ES6 version of JavaScript which we would be taking a look at next.

Object-Oriented Programming in ES6

ECMAScript (ES6) saw a lot of changes to how OOP is done in JavaScript and this has helped make the process of implementing OOP concepts in JavaScript easier.

In this section, we would look at some of the new concepts in ES6 which have had the biggest impact on how OOP works in the language.

The introduction of classes:

Classes were introduced in ES6 and this has changed a lot of things. It has also had a huge impact on the claims that JavaScript is not an object-oriented programming language due to its lack of classes.

The introduction of classes doesn’t change the fact that JavaScript is still prototype-based and not class-based.

Before ES6, objects were created this way:

var Shape = function (id, x, y) {
  this.id = id;
  this.move(x, y);
};

Shape.prototype.move = function (x, y) {
  this.x = x;
  this.y = y;
};

After ES6 and the introduction of classes:

class Shape {
  constructor (id, x, y) {
    this.id = id
    this.move(x, y)
  }
  move (x, y) {
    this.x = x
    this.y = y 
  }
}

With classes introduced in ES6, it is easier to thinking clearly in OOP terms especially for developers moving from other programming languages into JavaScript.

The use of “extends” for inheritance:

Inheritance before ES6 was not direct. You had to call the superclass while creating a “variable” in JavaScript then implement the inheritance using prototype-based inheritance.

In ES6, the extends keyword has been introduced which can be used to directly inherit classes.

Before ES6:

var Rectangle = function (id, x, y, width, height) {
  Shape.call(this, id, x, y);
  this.width = width;
  this.height = height;
};

Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

After ES6:

class Rectangle extends Shape {
  constructor (id, x, y, width, height) {
    super(id, x, y)
    this.width = width
    this.height = height
  }
}

Accessing base class attributes and methods:

Thanks to the implementations in ES6, class methods and attributes can now be accessed, overridden and even extended. Therefore just like you find with class-based prototyping, attributes and methods can be overridden.

Overriding methods using ES6:

class Shape {
  toString () {
    return `Shape(${this.id})`
  }
}

class Rectangle extends Shape {
  constructor (id, x, y, width, height) {
    super(id, x, y)
  }
  toString () {
    return "Rectangle > " + super.toString()
  }
}

Using getters and setters:

Data hiding is one of the side effects of encapsulation. Due to the new features in ES6, getters and setters can easily be implemented in JavaScript.

Using getters and setters in ES6:

class Rectangle {
  constructor (width, height) {
    this._width = width
    this._height = height
  }
  set width (width) { this._width = width }
  get width () { return this._width }
  set height (height) { this._height = height }
  get height () { return this._height }
  get area () { return this._width * this._height }
}

var r = new Rectangle(50, 20)
r.area === 1000

Finishing Thoughts

JavaScript is one language that has proven that a language doesn’t have to be class-based before it can be considered to be object-oriented. The language is doing fine with objects using prototypes instead of classes.

Regardless of the changes seen in ES6, some developers stand on the fact that the language is not object-oriented. However, the majority of developers agree that JavaScript is indeed an object-oriented programming language.

Everyone is free to let their opinions known on this matter. Do you feel JavaScript is not an object-oriented programming language despite the recent changes? Do you have other reasons besides those stated in this article as to why JavaScript is object-oriented? What are your thoughts on this issue? share with us.