What the heck is an object prototype? This isn't the Java I know and love! Argh!! In this video I break down parent-child relationships inherent to all objects in JavaScript and why understanding this matters.
So, a fundamental piece of OOP in JavaScript: all objects in JavaScript are interconnected in a parent-child relationship. The way that they actually connect is via this invisible chain, and the property which will give us access to that chain is something called [[Prototype]].
If I open up a new browser tab and enter into the browser devtools, into the `console` tab, I want to see that chain link from the parent to the child.
In JavaScript, there is a single `parent` object which exists as a `model` for all of the objects that we create. We want to see what the chain link looks like on this parent object. I'm going to create a new object using object literal syntax to instantiate it.
It says undefined - I haven't actually done anything with this variable yet, so this is expected. What I want to do is look at the properties of myObj - I'm going to open this little triangle icon to view this object's properties:
This is a new object, it has no properties yet, because I haven't done anything inside of it yet. But it has this one, kind of greyed-out, secret property, called [[Prototype]]. So where does this link to? Well, it's a pointer to another object - if you've seen some of my other videos, we know that this all objects in JavaScript are `passed by reference`. So it is referencing another object called `Object`.
If we open this panel up we'll see all of the properties of Object. Now this chain, this connection between Object and all of the regular objects we create, is called the Prototypal Chain. It is called this because anytime we have this parent-child relationship between 2 objects, the parent is called the object's `Prototype`.
All objects in JavaScript inherit from Object. If I create more objects, they will all have a prototypal link to Object.
Similarly, we have something in JavaScript called Array. And when I create a new array, using array literal syntax (square brackets), this will now inherit properties from Array. So Array will be the Prototype of the array I just created. Interestingly, the Prototype of Array is Object. This means that when I instantiate a new array, it will inherit all of the available properties of the parent Prototype Array, as well as all of the properties of the grandparent Prototype Object.
If we re-enter the browser devtools and create a new array, then view the properties of this array, we can see a [[Prototype]] link to Array, then in Array we can see a [[Prototype]] link to Object.
So we always refer to an object's parent as its Prototype. But an object's prototype doesn't necessarily need to be Array or Object. We can actually create this parent-child relationships between 2 objects that we create, so that one can inherit properties from the other. In the past (up to ES6), we used do this using a special method called Object.create(). Nowadays, this method is essentially deprecated, but it is still instructive to show how the language works under the hood.
const myPerson = {
eyes: 'green',
greet: () => 'hello',
}
So we've created a new object here, myPerson, and we want this to act as the `parent`, so that other objects can have a link to myPerson. If I create an object called Chris, using Object.create()...
const chris = Object.create(null);
...And if I were to pass in null, what do we think will happen? This will create an empty object. In the past, this newly created object would have a [[Prototype]] link, but interestingly, this seems to have now been removed as a feature. Where do we think the [[Prototype]] of this new object would have linked to? Well, if we use null here, then the [[Prototype]] would link up to Object, just like what we saw when we created a new object using object literal syntax (brackets). These days, with improvements to the language, Object.create(null) actually just seems to create an empty object with nothing inside it at all!
I want my chris object to inherit properties from myPerson. In other words, I want myPerson to be the parent, and chris to be the child. How do we do that? We will pass in myPerson as the argument to Object.create().
const myPerson = {
eyes: 'green',
greet: () => 'hello',
}
const chris = Object.create(myPerson);
Let's now take a look at chris in the browser devtools and see what happened - I'm going to paste this in:
We see here that Object.create() created an object - and let's open it up and take a look at its properties - let's see where the [[Prototype]] links to:
We can see that the properties of its Prototype - its parent - are the properties of myPerson. And we can see that this object's [[Prototype]] links to Object. So you can see that by using the Object.create() method, passing in a reference to another object, we have effectively created a parent-child relationship between 2 objects which we have created. We'll explore why this is useful in more depth later.
Why is this useful? When we want to look up a property on an object, that object might not have the property we are looking for. So what JavaScript will do is it will say, okay, this current object doesn't have the property we're looking for, so let's look up the prototypal chain to see if maybe some ancestor of this object has that property. If this property doesn't exist anywhere in the prototypal chain, it will return undefined.
This process of searching up the prototypal chain is called delegation.