Prototypal Inheritance on Built-In Objects
In this lecture, we will have a look at prototypal inheritance and the prototypal chain on built-in objects such as arrays. But before we do that, let's start by inspecting some of the stuff that we just talked about in the previous lecture. We will keep using the evan
object as an example. Let's get to it.
Let's start by taking a look at evan.__proto__
. And we already know it is the prototype of evan
, which is exactly the prototype property of Person
.
console.log(evan.__proto__);
But now, let's actually move up in the prototype chain, and essentially take a look at the prototype of evan's prototype.
console.log(evan.__proto__.__proto__);
Do you remember what that's going to be from the previous lecture? Well, it is the prototype property of Object
.
That's why you can see that the value of the constructor property is Object
. And then next to it, you see the hasOwnProperty
method that we talked about in the previous lecture. Hence, this is the reason why we were able to do evan.hasOwnProperty('firstName')
.
Next, let's take this one step further and take a look at the prototype of the prototype of the prototype 😅.
console.log(evan.__proto__.__proto__.__proto__);
Do you remember what this one is? Well, it is null
. And that's because Object.prototype
is usually the top of the prototype chain.
Let's also have a look at the strange constructor
property that we also talked about in the previous lecture.
console.log(Person.prototype.constructor);
Just as we learned in the previous lecture, it will point back to the Person
function itself.
To inspect the function, use the console.dir
method.
console.dir(Person.prototype.constructor);
Let's now talk about prototypes in arrays. Let's start by creating an array.
const arr = [1, 6, 3];
Let's now take a look at the prototype of the array.
console.log(arr.__proto__);
If you check your console
, and from the above image, you can see we have a list of methods, some of which we have already seen. For example, includes
, filter
, find
, and every
. And so this is the reason why all the arrays get access to these methods. So each array does, of course, not contain all of these methods. Instead, each array will inherit these methods from its prototype.
And we can also check that arr.__proto__
is the prototype of Array
.
console.log(arr.__proto__ === Array.prototype); // true
Just like objects, using the shorthand ([]
) to create an array is the same as using the new
keyword to create an array.
// new Array === []
Let's move one step further in the prototype chain and see what we get.
console.log(arr.__proto__.__proto__);
As expected, we get the prototype of Object
. You will notice that if you check the documentation of the find
method, for example, on MDN, you will see that the name of the method is Array.prototype.find
. And that's because the find
method lives in the prototype property of the array constructor function. One more time, you can see that prototypal inheritance is really a mechanism for reusing code. So all of those built-in methods have to exist only once somewhere in the JavaScript engine, and then all the arrays in our code get access to them through the prototype chain and prototypal inheritance.
Let's now move another step further. At this point, we know that any array inherits all its methods from its prototype. Hence we can use that knowledge to extend the functionality of arrays even further. All we will have to do is to add a new method to the prototype property of the array constructor, and all the arrays will then inherit it.
Let's say we want to add a new method to the array prototype that returns all the unique elements of an array.
Array.prototype.unique = function () {
return [...new Set(this)];
};
Let's now use this new method on our array.
const arr = [1, 6, 1, 4, 5, 2, 9, 7, 9, 6, 5, 3];
console.log(arr.unique()); // ==> [ 1, 6, 4, 5, 2, 9, 7, 3 ]
However, what we just did here, i.e., extending the prototype of a built-in object, is generally not a good idea. What I mean is, if you're working on a small project on your own, then that would be fine. But really, don't get into the habit of doing this for two main reasons:
It's fun implementing it 🤩 but in practice, you should probably not do it 🛑.