JavaScript - Prototypal Inheritance

Written by Joseph Lynn

JavaScript is a prototype-based language that has prototypal inheritance. Which is not the same as classical inheritance. Prototypal inheritance is more flexible than classical inheritance. With classical inheritance, you inherit all of the parent's methods. With prototypal inheritance, you can inherit specific functions by adding them to the .prototype.

I'll give some code examples below and here is the code sandbox to view the code as well.

Reference: class vs prototypal Reference: inheritance and the prototype chain Reference: Object prototypes Reference: Constructor Pattern

Classes are functions

Creating a class in JavaScript is syntax sugar (makes your code more readable). When creating classes, you are creating a function that serves as a constructor (a function called with the new operator). Here is what that looks like:

Reference: new operator

// constructor function
function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}

// creating an instance method on Person
// this method can be called on any new instance of Person
Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

// creating an instance method on Person
// this method can be called on any new instance of Person
Person.prototype.getAge = function () {
  return this.age;
};

console.log(typeof Person); // => function

// creating an instance of Person
const user = new Person("Joe", "Lynn", 27);
console.log(user.getFullName()); // => 'Joe Lynn'
console.log(user.getAge()); // => 27

Class implementation of above example

// create User class
class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  // creating a method getFullName()
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  // creating a method getAge()
  getAge() {
    return this.age;
  }
}

console.log(typeof User); // => function

const user2 = new User("Sierra", "Lynn", 26);
console.log(user2.getFullName()); // => 'Sierra Lynn'
console.log(user2.getAge()); // => 26

What is a prototype?

All JavaScript objects inherit properties and methods from a prototype. A prototype is an object that lets you store properties and methods that we want to be inherited further down the prototype chain.

// Object prototype
{
  constructor: ƒ Object()
  hasOwnProperty: ƒ hasOwnProperty()
  isPrototypeOf: ƒ isPrototypeOf()
  propertyIsEnumerable: ƒ propertyIsEnumerable()
  toLocaleString: ƒ toLocaleString()
  toString: ƒ toString()
  valueOf: ƒ valueOf()
  __defineGetter__: ƒ __defineGetter__()
  __defineSetter__: ƒ __defineSetter__()
  __lookupGetter__: ƒ __lookupGetter__()
  __lookupSetter__: ƒ __lookupSetter__()
  get __proto__: ƒ __proto__()
  set __proto__: ƒ __proto__()
}

What is the prototype chain?

The prototype chain is what makes inheritance possible. Every object in JavaScript inherits the prototype Object. You can walk up the prototype chain until you hit null.

console.log(Object.getPrototypeOf(user)); /* => 
{
  getAge: ƒ ()
  getFullName: ƒ ()
  constructor: ƒ Person(firstName, lastName, age)
  __proto__: Object
}
*/
console.log(Object.getPrototypeOf(Object.getPrototypeOf(user))); /* =>
{
  constructor: ƒ Object()
  hasOwnProperty: ƒ hasOwnProperty()
  isPrototypeOf: ƒ isPrototypeOf()
  propertyIsEnumerable: ƒ propertyIsEnumerable()
  toLocaleString: ƒ toLocaleString()
  toString: ƒ toString()
  valueOf: ƒ valueOf()
  __defineGetter__: ƒ __defineGetter__()
  __defineSetter__: ƒ __defineSetter__()
  __lookupGetter__: ƒ __lookupGetter__()
  __lookupSetter__: ƒ __lookupSetter__()
  get __proto__: ƒ __proto__()
  set __proto__: ƒ __proto__()
}
*/
console.log(
  Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(user)))
); // => null

Thanks for checking out this post. Please leave feedback on what can be improved/corrected. I always want to learn more.