Prototypes
We've already discovered there are two types of data in JavaScript:
- Primitives
- Objects
You can view a value's prototype by accessing the .prototype property
Let's start by finding out what data types have prototypes
constname='Marilyn';
console.log(typeofname);
//string
console.log(typeofname.prototype);
//undefined
constage=21;
console.log(typeofage);
//number
console.log(typeofage.prototype);
//undefined
constisAlive=true;
console.log(typeofisAlive);
//boolean
console.log(typeofisAlive.prototype);
//undefined
constnullValue=null;
console.log(typeofnullValue);
//object
console.log(typeofnullValue.prototype);
//TypeError:Cannotreadproperty'prototype'ofnull
constunknown=undefined;
console.log(typeofunknown);
//undefined
console.log(typeofunknown.prototype);
//TypeError:Cannotreadproperty'prototype'ofundefined
So far we've found out that primitive data types do not have prototypes.
Object Prototypes
Arrays
constshoppingList=['hummus','avocado','batteries'];
console.log(typeofshoppingList);
//object
console.log(typeofshoppingList.prototype);
We can see from above that arrays don't have prototypes
Plain objects
constobectOfMyAffection={
name:'Anonymous',
address:'Neveryoumind'
}
console.log(typeofobectOfMyAffection);
//object
console.log(typeofobectOfMyAffection.prototype);
//undefined
We can see from above that plain objects do not have prototypes
Functions
//functiondeclaration
constmakeMe=function(){
console.log('makeme');
}
console.log(typeofmakeMe);
//function
console.log(typeofmakeMe.prototype);
//object
//arrowfunction
constdareMe=()=>{
console.log('dareme');
}
console.log(typeofdareMe);
//function
console.log(typeofdareMe.prototype);
//undefined
Function declarations have prototypes but arrow functions do not.
Classes
classClassyPerson{
}
console.log(typeofClassyPerson);
//function
console.log(typeofClassyPerson.prototype);
//object
constnewClassyPerson=newClassyPerson();
console.log(typeofnewClassyPerson);
//object
console.log(typeofnewClassyPerson.prototype);
//undefined
- classes are functions which create objects. This is confirmed on line 5, we see that ClassyPerson is a function. The class keyword is syntax sugar for a function declaration.
- Functions inherit from the object prototype. We will cover what this means below.
- Classes return plain objects.
- Plain objects do not have prototypes, hence why the new instance of ClassyPerson (newClassyPerson) has no prototype.
What we have learned here is that of the object data type, only function declarations, classes (not instances of a class) have prototypes
Inheritance
Inheritance is a way for different object to share the same code. That code can be keys, values or methods.
Constructor Functions
A constructor function is a function which you can call, to create new objects.
They should always be capatalised. This is how we differentiate them from regular functions.
Example of a constructor function:
functionCar(make='defaultmake',model='defaultmodel'){
this.make=make;
this.model=model;
}
constcustomCar=newCar('custommake','custommodel');
console.log(customCar.make,customCar.model);
//custommakecustommodel
Car.prototype.drive=function(){
console.log('vroom!');
}
console.log(Car.prototype.hasOwnProperty('drive'));
//true
console.log(customCar.prototype.hasOwnProperty('drive'));
//TypeError:Cannotreadproperty'hasOwnProperty'ofundefined
console.log(Car.hasOwnProperty('drive'));
//false
console.log(customCar.hasOwnProperty('drive'));
//false
Car.prototype.drive();
//vroom!
customCar.drive();
//vroom!
/*SETTINGAPROTOTYPE*/
customCar.__proto__=Car;
console.log(customCar.prototype.hasOwnProperty('drive'));
//true
We are seeing prototypal inheritance at play here.
When a new instance of an object is created, if you try to call a method on that instance, in the following order this will happen:
- It will try to search for the method on the instance itself
- If it is not available on the instance, it will search on the instance's parent's prototype. On line 17, we see that drive is not available on the instance.
- A link is created from the parent prototype to the instance, which gives the instance access to all the methods and properties of the parent's prototype. This is why the method call on line 24 works - drive is a reference to customCar's parent's prototype, which customCar has a link to. This is what is meant by prototypal inheritance, it is actually a "delegation", not an inheritance in the real sense.
- If we want to explicitly set an instance's prototype, we can do so with .__proto__
Summary:
- Primitive data types, plain object, arrow functions do not have prototypes
- Of objects, only function declarations and classes (not instances of a class) have prototypes. classes are syntax sugar for function declarations.
Further reading
https://hackernoon.com/understanding-javascript-prototype-and-inheritance-d55a9a23bde2