Striping down the Prototype Chain
Tags: javascript, webdev, programming, beginners
Published: 2021-12-04 15:18:03

Sometimes I feel that a bunch of developers try to learn JavaScript but they only focus on top-level abstractions and they choose the path of learning the ___what it does___, and not ___how it is done___.

With that being said, let me ask you something: Do you _know_ how something is evaluated as `undefined` under the hood?

If you don't know how it works, this article is for you, little Padawan.


### It's all about prototypes

Whenever you see a class in JavaScript you're being lied about it. There's no such thing in JS. It is all about prototypes.

The ES2015 release brought the concept of "classes" into the world and the people use it a lot. Some of them don't know that classes are just a syntactical sugar. In the end, JS is a __prototype-based__ language.

#### :key: Prototype access on objects and functions

In order to add properties to objects you can use `__proto__`:

```js
 const myObject = { x: 1 }

 myObject.__proto__.y = 2
```

However if you intend to add properties to functions, you need to use the `prototype` access:

```js
 const myFunction = function() { this.a = 1 }

 myFunction.prototype.b = 2
```

### The Prototype Chain

JavaScript has only one construct: Objects.

Each one of these objects has a private property called __prototype__. `Prototype` is also an object therefore it contains the __prototype__ property on its own. This chain continues until the last `prototype` has the value of `null`.

Okay, but let me show you a practical example before you fall asleep:

```js
// Create a real simple object
const myCustomObject = {
  x: 1,
  y: 2
}
```

If you put this on your browser's console and console log it you'll see something like this:

![Result of a console.log function showing the properties of an object and its prototype](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qy05e04pb8t66d45vjnu.png)

As you can see, there's the expected properties from the object `x` and `y` plus the `[[prototype]]` object.

Try to expand this last one:

 ![Prototype object expanded](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/435o5yeiav23sevz5muo.png)

There's a lot of things inside of it: a constructor, and some functions which can be used by this object. Each one of these  have a `prototype` on its own. Expand them and check it out.

But again: the prototype itself has a `__proto__` (same as [[prototype]]). Ok, let's expand it until the very end of the chain. 

![The prototype chain fully expanded](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6i6kzimpvxinijuuk2s.png)
 
 
[...] and that's the end of the prototype chain. That's all, folks...

Just kidding, haha

### Inheritance

Before we enter on the last topic of this article I would like to show you a little bit about how the inheritance happens with this prototype-based thing.

```js
let myCustomFunction = function () {
   this.x = 1;
   this.y = 2;
}

// create a new object from myCustomFuncion()
// with its own properties
let instanceOfMyCustomFunction = new myCustomFunction(); 

// add two new properties to myCustomFunction's prototype
myCustomFunction.prototype.y = 3;
myCustomFunction.prototype.z = 4;
```

Hm, right... Let's see how interesting all of this is.

```js
  console.log(myCustomFunction.x); // 1
  console.log(myCustomFunction.y); // 2
  console.log(myCustomFunction.z); // 4
  console.log(myCustomFunction.t); // undefined
``` 

Wait, wait, wait... y is not 3? how's that?! :eyes:

JS will look for a given property by checking the object properties first, then it will check the first prototype and so on until it finds the `__proto__: null`.

Check this out:

```js
// JS finds the `x` property on myCustomFunction object
console.log(myCustomFunction.x); // 1

// JS finds the `y` property on myCustomFunction object
console.log(myCustomFunction.y); // 2
```

Ok, but why the heck this is 2 and not 3? That's simple:

JS will return the first result found. In this case, 2 is the first value found.

If there was no y property on the base of the object, JS would search for it on ___object's prototype___. 

This is exactly what is happening with the `z` property:

```js
// JS doesn't find the `z` property on myCustomFunction object
// so it searches on its prototype, where it's available
console.log(myCustomFunction.z); // 4
```

Finally, when no value is found, JS assume that the property ___is not defined___ therefore the undefined value shows up:

```js
// there's no `t` property whatsoever on the prototype chain.
console.log(myCustomFunction.t); // 4
```
### One last example

```js
let myCustomFunction = function () {
   this.x = 1;
   this.y = 2;
}

myCustomFunction.prototype.foo = "bar"

let instanceOfMyCustomFunction = new myCustomFunction(); 

instanceOfMyCustomFunction.prop = "some value"


console.log(instanceOfMyCustomFunction.prop); // some value
console.log(instanceOfMyCustomFunction.foo); // bar
console.log(myCustomFunction.prop); // undefined
console.log(myCustomFunction.foo); // undefined
console.log(myCustomFunction.prototype.prop); // undefined
console.log(myCustomFunction.prototype.foo); // bar
```

I hope this helps you to understand better what's going on under the JS' hood and if I missed something, let me know by commenting on this article! 

Thanks for reading! See ya!