Hello people, I hope you’re all doing right. I’m a bit confused about the concept of prototypal inheritance. I understand that each object has a public, non enumerable property called prototype, and that this property is either an object or null.
So, when I use the new keyword, the object inside the prototype property of the constructor will be linked to the new object as its [[Prototype]]. For instance:
let object = {title: 'FreeCodeCamp', status: 'super happy'};
function Build(){} //shallow function
let newObject = new Build; /*//look into Build's prototype property and link it to the new object as its *[[Prototype]]*.
(I understand the *prototype* property is triggered only
when we call a function with the *new* keyword,
and also that we literally mean a regular property called 'prototype')*/
//At this point, the *prototype* of Build it's just
//an object with just one property, *constructor*, that points to //the function itself
Build.prototype.constructor //[Function: Build]
//Of course, I can change it:
let testObject = {
coolProperty: "I'm cool",
available: true
}
Build.prototype = testObject;
Build.prototype // { coolProperty: 'I\'m cool', available: true } is now the object stored inside the 'prototype' property of Build
let x = new Build; //it's the same as saying: link x to { coolProperty: 'I\'m cool', available: true }
We know that, in prototypal inheritance (one of the coolest things about JS), if a property is missing from an object the [[Prototype]] chain will be looked up. In the case above, x does not have a ‘coolProperty’ ; but the engine looks up at the prototypal chain and finds ‘coolProperty’ in testObject. Great, we’ve got. So where is my confusion? It’s probably because I confuse the literal prototype (that is, a regular property that exist inside an object) and [[Prototype]] (probably because of that ‘link the object present into prototype to the newly crated object as its [[Prototype]]’. For instance:
//literal object
let x = {};
//function
function func(){}
Object.getOwnPropertyDescriptor(func, 'prototype'), //the functions does have a prototype property
Object.getOwnPropertyDescriptor(x, 'prototype') //undefined
So all objects have a prototype that is either another object or null. Why then can I access the one inside func but not inside x? Both are instances of Object; both [[Prototype]] chains end with it, then null… What is really this prototype property? To me it seems a key that stores just the next level of the prototypal chain. Because, if the chain was literally stored inside of it, and If we had to use it to reach to the [[Prototypal]] for properties we don’t have in our object, a simple snippet like this one would cancel the whole chain:
let x = {}; //empty object
x.prototype = null; //set the prototype to null
x.hasOwnProperty(); //I can still borrow methods from the Object ancestor
//here we really cut off an object from the prototypal chain
let y = Object.create(null);
y.toString() //TypeError: y.toString is not a function (we cannot get it from Object)
I can clearly see that the prototype property has nothing to do with the [[Prototype]], which is hidden. So is it just a key that stores the next level of the chain? (that stores another level and so on till the Object). I’m sorry for this super long post, but I’m still quite confused about it…