Prototypes

Objectives

  • Understand what the prototype object is

  • Describe and diagram the relationship between __proto__, prototype and constructor

  • Add methods and properties on the prototype object to write more efficient code

  • Explain the differences between adding methods and properties to the prototype versus the constructor function

The new keyword

  • Creates an object out of thin air

  • Assigns the value of 'this' to be that object

  • Adds 'return this' to the end of the function

  • Creates a link (which we can access as __proto__) between the object created and the prototype property of the constructor function 

We previously used the new keyword to create objects from constructor functions - let's recap what it does

We're going to focus on the 4th point - let's see what that link looks like!

A Small Diagram

  • Every constructor function has a property on it called "prototype", which is an object
  • The prototype object has a property on it called "constructor", which points back to the constructor function
  • Anytime an object is created using the 'new' keyword, a property called "__proto__" gets created, linking the object and the prototype property of the constructor function

Person

Person

.prototype

elie

colt

.__proto__

.prototype

.constructor

Code

// this is the constructor function
function Person(name){
    this.name = name;
}

Let's see that previous example in code - feel free to look back at the diagram

// this is an object created from the Person constructor

var elie = new Person("Elie");
var colt = new Person("Colt");
// since we used the new keyword, we have established
// a link between the object and the prototype property
// we can access that using __proto__

elie.__proto__ === Person.prototype; // true
colt.__proto__ === Person.prototype; // true
// The Person.prototype object also has a property
// called constructor which points back to the function

Person.prototype.constructor === Person; // true

Prototype

Where does the prototype property fit into all of this? Remember, the prototype is shared among all objects created by that constructor function

// this is the constructor function
function Person(name){
    this.name = name;
}

// this is an object created from the Person constructor

var elie = new Person("Elie");
var colt = new Person("Colt");
Person.prototype.isInstructor = true;

elie.isInstructor; // true
colt.isInstructor; // true

// how were we able to access properties on the prototype??

// __proto__!

Prototype Chain

How does JavaScript find methods and properties?

Array

Array

.prototype

.__proto__

.prototype

.constructor

.__proto__

Object

.prototype

.__proto__

arr

null

Refactoring 

function Person(name){
    this.name = name;
    this.sayHi = function(){
        return "Hi " + this.name; 
    }
}

elie = new Person("Elie");
elie.sayHi(); // Hi Elie

// now this code works, but it is inefficient
// every time we make an object using the new keyword we have to redefine this function
// but its the same for everyone! Let's put it on the prototype instead!

Now that we know that objects created by the same constructor have a shared prototype, let's refactor some code

function Person(name){
    this.name = name;
}

Person.prototype.sayHi = function(){
    return "Hi " + this.name; 
}

elie = new Person("Elie");
elie.sayHi(); // Hi Elie

// Muchhh better

Your turn!

  • Create a constructor function for a Vehicle: every object created from this constructor should have a make, model, and year property. Each object should also have a property called isRunning, which should be set to false

 

  • Every object created from the Vehicle constructor should have a function called turnOn, which changes the isRunning property to true

 

  • Every object created from the Vehicle constructor should have a function called turnOff, which changes the isRunning property to false

 

  • Every object created from the Vehicle constructor should have a method called honk, which returns the string "beep" ONLY if the isRunning property is true

Solution

function Vehicle(make, model, year){
    this.make = make;
    this.model = model;
    this.year = year;
}


Vehicle.prototype.isRunning = false;

Vehicle.prototype.turnOn = function(){
    this.isRunning = true;
}

Vehicle.prototype.turnOff = function(){
    this.isRunning = false;
}

Vehicle.prototype.honk = function(){
    if(this.isRunning){
        return "beep!";
    }
}

Recap

  • Every time the new keyword is used, a link between the object created and the prototype property of the constructor is established - this link can be accessed using __proto__

  • The prototype object contains a property called constructor, which points back to the constructor function

  • To share properties and methods for objects created by a constructor function, place them in the prototype as it is the most efficient

Prototypes

By Elie Schoppik

Prototypes

An introduction to Prototypes in JavaScript

  • 1,614