OOPS

We learned about objects before. Now let's learn about object-oriented programming.

We’ve talked about objects before.

Object oriented programming takes objects at a whole new level.

In this unit you’ll discover classes, how to create methods, what are constructors, how to use inheritance, and then we’ll talk about one of the most confusing (but fundamentals) aspects of JavaScript: protypes.

Classes

Classes are a way to define a common pattern for multiple objects definitions.

In other words, you define a class and then all objects that you create from that class have the same properties and methods of the class.

It’s like a template.

We can create a class named Person (note the capital P, a convention when using classes), that has a name property:

class Person {
  name
}

You can set a default value using this syntax:

class Person {
  name = 'Flavio'
}

Note: remember, don’t use a : colon for class properties, but use =. It’s a bit confusing with object properties.

Now from this class, we initialize a flavio object like this:

flavio is called an instance of the Person class, and inherits all the properties (and methods, too, as we’ll see) of the Person class.

We can now access the name property on flavio using the dot syntax we use for objects:

Class methods

Just like you can add methods to objects, you can add methods to classes.

Methods are defined in this way:

A class method is like a function, but without the function keyword.

We can invoke methods on an instance of the class:

If you are wondering what is the difference with methods defined on object literals:

There’s no difference, apart from the fact that all objects instantiated from the class will inherit the method, so they don’t need to define it themselves.

Private class properties

When you define a property on a class, once you got an object you can access that property freely, getting and setting its value.

Sometimes however it’s important to keep things private.

We can use private class fields that enforce private fields:

We now can’t access this value from the outside.

You need to add a method to get its value:

Constructors

You can create an object from the class passing arguments that are then stored inside the object.

We do so using a constructor, a special method of the class.

Here’s an example:

When the object is initialized, the constructor method is called, with any parameters passed.

Now we can add methods that use the name property:

Notice we used this to reference the class. This is another place where you are going to use this special JavaScript keyword, other than in object methods.

Inheritance

A class can extend another class, and objects initialized using that class inherit all the methods of both classes.

Suppose we have a class Person:

We can define a new class Programmer that extends Person:

Now if we instantiate a new object with class Programmer, it has access to the hello() method:

The JavaScript instanceof operator returns true if the first operand is an instance of the object passed on the right, or has it in its inheritance chain.

In this example you can see that the myCar object, of class Fiesta, responds true to instanceof Fiesta, and also responds true to instanceOf Car, because Fiesta extends Car:

In the constructor() method we can also call super() to invoke the same method in the parent class.

Suppose you have a class Car:

and in this class we have a constructor() method:

You can have a Tesla class that extends the Car class:

The Tesla class inherited all the methods and properties of Car, including the constructor method.

We can create an instance of the Tesla class, creating a new myCar object:

The original constructor in Car is executed, because Tesla does not have one of its own.

We can override the constructor() method in the Tesla class:

and

will print This is a Tesla.

In the constructor() method we can call super() to invoke the same method in the parent class:

Calling

will now execute 2 console logs. First the one defined in the Car class constructor, the second the one defined in the Tesla class constructor:

Note that super() can only be called in the constructor, not in other methods.

And we can pass in any parameter to the parent class, if the constructor accepts parameters.

Prototypes

The concept of prototype is a peculiar feature of the JavaScript language.

I’m going to wear the “old guy” hat here, and tell you that before 2015, we didn’t have classes in JavaScript. And we didn’t have the easy inheritance they provide.

But we could still implement some kind of inheritance using prototypes.

Now, in 2021 you likely won’t use prototypes directly in your code, but that’s how JavaScript classes work under the hood, so it’s still something you should know as a JavaScript programmer.

Not to mention you need to understand when you read code that uses them.

Constructor functions

Before introducing prototypes I need to introduce constructor functions.

In JavaScript we can use the new keyword to create objects using a function that’s called constructor function. It’s just a function but we use it to create an object constructor, in this way:

By convention, we use an uppercase letter to define the function, but it’s not mandatory

Remember constructors when we talked about classes? It’s basically the same thing, but with a different syntax.

Now we can initialize new objects using the new keyword, like this:

Each of those objects points to a prototype

Every object in JavaScript has a prototype property that points to its prototype.

What is the prototype of tesla and bmw? It’s Car.

Both objects have the color property, as that’s set in the Car constructor.

See this special __proto__ property? That points to the object’s prototype.

What’s a prototype useful for?

Now here’s the fun part.

You can add other properties to the prototype:

Now both objects have the owner property, too.

If you assign the owner property a new value in one object:

The other object is independent:

But if you set it like this:

then bmw.owner is test too.

So basically Car is a common object that both instances inherit from.

Utility methods

JavaScript provides some utility methods to work with prototypes:

And the prototype of Car is Object:

which is also the prototype of tesla and bmw, because it’s a chain:

Object is the prototype of Car which is the prototype of tesla and bmw.

The chain ends at the Object object, which is a special snowflake.

An example with an array

If you initialize an array

the prototype is Array.

You can verify this by checking with the Object.getPrototypeOf() and the Object.prototype.isPrototypeOf() methods:

All the properties and methods of the prototype are available to the object that has that prototype.

Car has all the methods and properties provided by Object.

list has all the methods and properties provided by Array, PLUS all the methods and properties provided by Object, because Object.prototype is the base prototype of all the objects:

Using prototypes to write more efficient code

One thing that is often mentioned when introducing prototypes is that if you have a constructor for an object with a method, like this:

and you expect to have many instances of that object, and that function is heavy meaning it’s wasting memory, you can extract that method to the prototype:

So JavaScript instead of having 1000 functions for 1000 objects, it has just 1 for the prototype of those 1000 objects.

It’s not something I’ve done myself, as I don’t do any kind of high intensive applications, and I think it’s premature optimization to think about doing this kind of work to make the computer run faster.

But it’s worth knowing you have this possibility.

Last updated

Was this helpful?