Understanding classes and prototypes
Tags: javascript, webdev
Published: 2020-01-21 04:00:23

In this article I'll try approach in a simple and objective way what I've learned (thanks to Will Sentance) about object orientend in Javascript, wich is a very popular program paradigm to structure complex codes.

I'll initiate this with the principle of encapsulation, in how we can store data and their respective methods: **Objects**.

Let's start with the object vehicle.

```
const vehicle1 = {
  type: "Car",
  name: "Belina",
  speed: 0,  
  accelerate: function() { vehicle.speed++; }
};
```

Supose we need now to create a new vehicile, let do this with a diferent ways.

### Using the dot notation 🔨

```
const vehicle2 = {};; // creates a empty object
// assigns the properties to the object
vehicle.type = "Car";
vehicle.name = "Monza";
vehicle.speed = 0;
vehicle.accelerate = function() {
  vehicle2.speed++;
}
```

### Using Object.create() 🛠️

```
const vehicle3 = Object.create(null);
// assigns the properties to the object
vehicle3.type = "Car";
vehicle3.name = "Uno";
vehicle3.speed = 0;
vehicle3.accelerate = function() {
  vehicle3.speed++;
}
```

All right, every above ways be valids to create an object, however you may be feeling uncomfortable with the ways we're did that.

We're break a important principle in programming: ***Don't Repeat Yourself***

What we can do?

### Factories! Generating objects with functions 🏭

```
function vehicleCreator(type, name, speed) {
  const newVehicle = {};
  newVehicle.type = type;
  newVehicle.name = name;
  newVehicle.speed = 0;
  newVehicle.accelerate = function () {
    newVehicle.speed++;
  };
  return newVehicle;
};
```

Now we get eliminate the code copy every time we need to create a new vehicle.

```
const vehicle1 = vehicleCreator("Car", "Belina", 0);
const vehicle2 = vehicleCreator("Car", "Monza", 0);
vehicle1.accelerate();
```

We solve some of our problems. However, every time we've created a new vehicle we created unnecessary copies in the application memory of the ***accelerate*** method. That's sucks!

### Using prototype chain ⛓️

What if instead of creating a new method copy on each new object, we store our methods in other local and create a link these methods in the object, in a way what the interpreter can check the prototype chain and find them.

We can creat this link using ***Object.create()***

```
function vehicleFunctionStore() {
  accelerate: function() { this.speed++; }
}

function vehicleCreator(type, name, speed) {
  // the Object.create() serve to do the link between the new object created and the object methods vehicleFunctionStore.
  const newVehicle = Object.create(vehicleFunctionStore);
  newVehicle.type = type;
  newVehicle.name = name;
  newVehicle.speed = 0;
  return newVehicle;
}
```

Now, the way we created and used the methods of each object stay the same, however were not created unecessary copies of the method.

```
const vehicle1 = vehicleCreator("Car", "Belina", 0);
const vehicle2 = vehicleCreator("Car", "Monza", 0);
vehicle1.accelerate();
```

But, how this link with the objects works?

All Javascript object has one property called ***__proto__***.
This property links all Javascript objects to a another big one, the ***Object.prototype*** that contains a built-in methods.

It's exactly through this property we can access our ***accelerate*** method linked by ***Object.create()***

```
// When we execute the accelerate method, the interpreter goes to the object vehicle1 search for the method. However, this method doesn't exist in the object. 
So, the interpreter goes to the Object.Prototype to verifies if the method exists, and there can find it and execute it!

vehicle1.accelerate();
```

Great! We solve one more problem. But the things still out of the pattern here.
This approach is useful and works, but exists another ways to facilitate our job.

### The "new" keyword 🆕

```
// Let's change this way
const vehicle1 = vehicleCreator("Car", "Belina", 0);
const vehicle2 = vehicleCreator("Car", "Monza", 0);

// To this
const vehicle1 = new vehicleCreator("Car", "Belina", 0);
const vehicle2 = new vehicleCreator("Car", "Monza", 0);
```

However we need to do some adaptations in our code.

```
function vehicleCreator(type, name, speed) {
  this.type = type;
  this.name = name;
  this.speed = speed;
}
```

Notice now we don't have to create a new object neither return one.
The ***new*** keywords make do this for us! And is the only thing that word do.

Now we've to create our method's link in the ***__proto__*** property.

```
vehicleCreator.prototype.accelerate = function() {
  this.speed++;
}
```

This code have the same function what we did with de ***Object.create()***.
Now we can create our objects with this way.

```
const vehicle1 = new vehicleCreator("Car", "Belina", 0);
const vehicle2 = new vehicleCreator("Car", "Monza", 0);
```

All sweet, we facilitate so much the writing, performance and understanding of our code, but imagine that each new method we need to create a new link in prototype chain.

```
vehicleCreator.prototype.accelerate = function() {
  this.speed++;
}
vehicleCreator.prototype.decelerate = function() {
  this.speed--;
}
```

We need to write our methods separeted of our object constructor. Sounds me unusual.

### Javascript classes 🎩

From the ES2015 we had the insertion of syntactic sugar word ***class***.
This emerges like a new development pattern and looks like with other programming languages.

However, the ***class*** keyword, under the hood, make exactly the same thing that we had above in the ***The "new" keyword*** topic.

With it, we can declare our methods together with our object constructor and we don't need to explicitly link with prototype chain.

```
class VehicleCreator {
  constructor(type, name, speed) {
    this.type = type;
    this.name = name;
    this.speed = speed;
  }
  accelerate() {
    this.speed++;
  }
  decelerate() {
    this.speed--;
  }
}
const vehicle1 = new vehicleCreator("Car", "Belina", 0);
vehicle1.accelerate();
```

This code above, under the hood, make exactly the same thing of the code below, but is more elegant.

```
function vehicleCreator(type, name, speed) {
  this.type = type;
  this.name = name;
  this.speed = speed;
}
vehicleCreator.prototype.accelerate = function() {
  this.speed++;
}
vehicleCreator.prototype.decelerate = function() {
  this.speed--;
}
const vehicle1 = new vehicleCreator("Car", "Belina", 0);
vehicle1.accelerate();
```

I'm end my article here. I've tried - and hope that I have succeeded - explain succinctly and direct about ***prototype chain***, the diference between ***__proto__*** property and ***prototype*** (the big object), and the way what ***new*** and ***class*** keywords help us to object creation.

See you soon!👋

[Understanding closures](https://vequiato.dev/blog/understanding-closures-h2b/245969)
[Understanding Higher Order Function](https://vequiato.dev/blog/understanding-higher-order-function-1dlg/250804)