Introduction to Prototypes 

Overview

  • Prototype Chain
    • Internal Prototypes
  • `.prototype` property
  • `new` Keyword
  • `.__proto__` vs `.prototype`

The Prototype Chain

  • Objects have links to other objects, via the internal [[Prototype]] object and the Prototype Chain.
  • The internal [[Prototype]] is accessed when a property (or method) is called on an object but the property isn't present on the current object.

Object 1

Object 2

Object 3

null

The Prototype Chain

const mySundae = ['cherry', 'vanilla', 'sprinkles'];

const yourSundae = ['chocolate', 'hot fudge', 'walnuts'];

mySundae.join("");

yourSundae.join("");

mySundae

.length

0: 'cherry'

1: 'vanilla'

2: 'sprinkles

yourSundae

.length

0: 'chocolate'

1: 'hot fudge'

2: 'walnuts

Array.prototype

.join

.pop

.push

Prototype Chain

Prototype Chain

Functions & the `.prototype` property

  • Only Function objects have a `.prototype` property.
  • Function objects also have an internal prototype.
  • The `.prototype` is NOT the internal prototype.
  • .__proto__ === internal prototype.
function helloWorld(){
}

/*helloWorld.prototype = {
    constructor: helloWorld
// internal Prototype === Object.prototype
}*/

What is the `.prototype` property used for?

...before answering this, we need to look into constructor functions!

Prototype Chain and `.prototype Recap

  • All values have an "internal prototype" that links the value to another object.  This is the prototype chain
  • The `.prototype` property is a property on all function objects, it is not the same object as the INTERNAL prototype.
  • Does a function object have an internal prototype AND a `.prototype` property?

What is a Constructor Function?

A Constructor Function returns an object called an instance, when it is invoked with the `new` keyword

function Person(name){
  this.age = 0;
  this.name = name;
}
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

Why do we need to create objects?

Create an Account

Account Info Saved

  • An Object is created after User Data  is stored in a Database.
  • We need to create the object programmatically...Twitter engineers do not add users manually.
  • Every "Twitter User" object will have standard properties and functions.
  • Use a "Constructor" function to create the Twitter User Objects
var scottTwitter = {
  name: 'Scott',
  email: 'email@email.com',
  password: '.....',
  handle: '@Scott',
  followers: []
  _id: 012345,
  joined: Thu March 01 2019 07:36:30 GMT-0500 (EST)
}
  

The `new` keyword

  • Used with a "constructor" function.
  • Invokes the constructor function.
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

The Four Actions of the `new` Keyword

  1. Invokes the constructor function.
  2. Creates an empty Object.
    • Links the `.prototype` property of the constructor function to the internal prototype of the empty object.
  3. Assigns the empty object to the "this".
  4. Implicitly returns "this" (which is the object created).

1. NEW: Invokes the constructor

The "new" keyword invokes the constructor function.

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

// STEP 1: new invokes Person
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

2. NEW: Creates an empty object

  1. Creates an empty object.
  2. The internal prototype of the empty object is assigned to the constructor functions `.prototype` property.
function Person(name) {
// STEP 2: {} the internal prototype === Person.prototype
 this.age = 0;
 this.name = name;
}

// STEP 1: new invokes Person
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

3. NEW Assigns the "this" keyword

Assigns the "this" keyword to the object created by the new keyword.

function Person(name) {
// STEP 2: {} the internal prototype === Person.prototype
// STEP 3: this = {} (object created in STEP2)
 this.age = 0;
 this.name = name;
}

// STEP 1: new invokes Person
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

4. returns "this"

  • Implicitly returns the "this" keyword.
function Person(name) {
// STEP 2: {} the internal prototype === Person.prototype
// STEP 3: this = {} object created in STEP 2
 this.age = 0;
 this.name = name;
/* STEP 4: return this 
    - this === {age:0, name:'Karen'}
    - internal prototype === Person.prototype */
}

// STEP 1: new invokes Person
var karen = new Person('Karen');

/* karen = {
  age:0,
  name: 'Karen',
} */

Instance

An "instance" is an object created by a constructor function.

function Person(name) {
 this.age = 0;
 this.name = name;
 this.speak = function(){
   return 'hello';
 }
 this.eat = function(){
   return "I'm full!";
 }
}
var karen = new Person('Karen');
var scott = new Person('Scott');

karen

age

name

speak

eat

scott

Person.prototype

age

name

speak

eat

constructor: Person

Method Placement

  • Universal methods should be placed on the `.prototype` object.
  • Instead of multiple copies/versions of the methods, there is only one method shared across every instance.
  • Easier to maintain and keeps code "DRY".
  • Let's see an example.

Method Placement

function Person(name) {
 this.age = 0;
 this.name = name;
}
Person.prototype.speak = function(){
   return 'hello';
 }
Person.prototype.eat = function(){   
   return "I'm full!";
}
var karen = new Person('Karen');
var scott = new Person('Scott');

karen.speak();
scott.eat();

karen

age

name

scott

Person.prototype

age

name

constructor: Person

eat

speak

`.__proto__` vs `.prototype`

  • .__proto__ is a function that shows the "internal prototype" of an object.
  • A property with an "_" normally indicates the property should be private or untouched.
  • .__proto__ is great for inspecting the prototype chain with developer tools, but, it should never be used in code.

deck

By Scott D'Alessandro