OOP II: Objects and prototype chain
Learning Goals
By the end of this lesson, you will be able to:
- Speak to and understand the difference between
prototoype
and__proto__
- Understand and explain how prototypal inheritance works via the prototype chain.
Vocab
prototype
A special object which is assigned to functions that you make in JavaScript[[prototype]]
A hidden link on every object that links objects to one another, allowing objects to share behaviors__proto__
Also called “dunder-proto”, this allows us to access the[[prototype]]
Prototype
Warm Up
Where have we heard the term prototype
before. What do we know about this so far?
Review
- We know that a prototype is a model of something and how it should look or behave.
- We know that we have access to prototype methods (forEach, filter, etc) on arrays.
What is a prototype?
In JavaScript, a prototype is a special object that is assigned to all functions, including but not limited to functions that are used to construct objects.
Take a look at the example below:
class Instructor {
constructor(name, primaryLesson) {
this.name = name;
this.primaryLesson = primaryLesson;
}
teachLesson(duration) {
if (duration > 3) {
return `${this.name} can\'t teach a lesson that long!`;
} else {
return `Gunna teach you all real good about ${this.primaryLesson}`;
}
}
gradeProjects(project) {
return `${this.name} is grading ${project}.`
}
}
let instructor = new Instructor('Hannah', 'OOP 2');
- After declaring this class, type
Instructor.
into your console. (Note the uppercaseI
) You should see the browser attempting to autocomplete this with properties that are available on this function. Look at theprototype
property and take note of its value.
Diving Deeper
By accessing the prototype
of our Instructor
class - we can see that it points to an object that has three methods: constructor
, teachLesson
, and gradeProject
. Our prototype
is a property on the function that points back to our Instructor
class.
Remember classes are actually functions. (also known as constructor functions). Before we had the syntax for classes, developers used constructor functions to create multiple objects from a template. Here is the same code from above written in ES5 syntax:
function Instructor(name, primaryLesson) {
this.name = name;
this.primaryLesson = primaryLesson;
}
Instructor.prototype.teachLesson = function(duration) {
if (duration > 3) {
return `${this.name} can\'t teach a lesson that long!`;
} else {
return `Gunna teach you all real good about ${this.primaryLesson}`;
}
}
Instructor.prototype.gradeProjects = function(project) {
return `${this.name} is grading ${project}.`
}
let instructor = new Instructor('Robbie', 'POST Requests');
In order to add methods to our template, we had to manipulate the prototype
directly. This is exactly what our classes do under the hood.
Review: What is a prototype?
A special object which is assigned to functions that you make in JavaScript
Another Look (In Breakout Groups)
From our prior example, take a look at the instructor
and take note of all the properties. (Note the lowercase i
)
It is likely that you have seen this (somewhat overwhelming) list of properties while working with other types of data in your console - not just functions and objects.
- After doing the above, declare an array literal named
food
in your console. (list the last three things you ate) - What happens when you type
food.
? - What is the browser attempting to autocomplete?
- What familiar properties are showing up?
- Is the
prototype
property still there? Why or why not? - Bonus: Try this out with other data types!
proto
You’ll notice that when we checked the instructor
instance and array literal in the console, there was no property of prototype
listed. This is because neither of these are functions, so the property of prototype
is not automatically assigned.
What is the proto?
Everything (including the Instructor
class) that we have checked in the console thus far has had the property __proto__
.
__proto__
, or “dunder-proto” (double-underscore proto), is a property that exposes the internal[[prototype]]
property.- This
[[prototype]]
property acts a as a reference that points to a function’s prototype object.
Note
It is this reference, or linking, between objects that makes up the prototype chain.
- The prototype chain (and objects linking in such a way) is what allows us to define behavior in one place (or one
prototype
object) and share it between many objects.
For example, using our instructor
variable, let’s use the valueOf
prototype method.
// Example #1
let instructor = new Instructor('Travis', 'OOP');
instructor.valueOf()
// {instructor: "Travis", module: 2}
// Example #2
let message = 'The prototype chain is super cool!';
message.valueOf();
// "The prototype chain is super cool!"
Strange…this isn’t a method we created on our Instructor
class. valueOf is actually an object prototype method! Why do we have access to this method on a string as well? What is happening?!
When the interpreter is attempting to access a property on an object, it will start by looking directly on that object. If that property is not found, the objects internal [[prototype]]
property will point to the object to examine next. The interpreter will continue to travese the prototype chain to seek a resolution for the property… until the end of the prototype chain is reached (resulting in null
).
It is this linking between objects that makes it so that objects are not limited to using the methods that are formally defined directly on that object - they can also ask objects further up the chain for help.
In Breakout Groups
With your partner, save all the data types that you can think of to variables. Using the console, check the [[prototype]]
link via the dunder-proto.
- What similiarties do you notice across data types? What differences?
- Can we say “everything is an object” in JavaScript?
Checks for Understanding
- Describe the prototype chain. Why is the chain in place? Why would the interpreter traverse this chain?
- What is the difference between
prototype
and__proto__
?