Notes

Constructor Functions

Defining a constructor function Example of an object using object initialiation

const fellowshipOfTheRing = {
  title: "The Fellowship of the Ring",
  series: "The Lord of the Rings",
  author: "J.R.R. Tolkien",
};
function Book(title, series, author) {
  this.title = title;
  this.series = series;
  this.author = author;
}

Invoking a constructor function

function Book(title, series, author) {
  this.title = title;
  this.series = series;
  this.author = author;
}

const fellowshipOfTheRing = new Book(
  "The Fellowship of the Ring",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

console.log(fellowshipOfTheRing); // Book { title: 'The Fellowship of the Ring', ... }

Understanding New Object Instances

Using the instanceof operator to check an object’s type

console.log(fellowshipOfTheRing instanceof Book); // true

Invoking a constructor function without the new keyword

Defining Sharable Methods

function Book(title, series, author) {
  this.title = title;
  this.series = series;
  this.author = author;
}

// Any method defined on the `Book.prototype` property
// will be shared across all `Book` instances.
Book.prototype.getInformation = function () {
  return `${this.title} by ${this.author}`;
};

const fellowshipOfTheRing = new Book(
  "The Fellowship of the Ring",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

console.log(fellowshipOfTheRing.getInformation());

The Problem with Arrow Functions


Putting the Class in Javascript Classes

In ES2015, JS gained the class keyword - replacing the need to use only constructor functions & prototypes to mimic classes!

Defining a ES2015 class

class Book {
  constructor(title, series, author) {
    this.title = title;
    this.series = series;
    this.author = author;
  }
}

Instantiating an instance of a class

Class Definitions are NOT hoisted

test();

function test() {
  console.log("This works!");
}

Defining Methods

class Book {
  constructor(title, series, author) {
    this.title = title;
    this.series = series;
    this.author = author;
  }

  // Notice the use of a rest parameter (...books)
  // to capture the passed parameters as an array of values.
  static getTitles(...books) {
    return books.map((book) => book.title);
  }

  getInformation() {
    return `${this.title} by ${this.author}`;
  }
}

const fellowshipOfTheRing = new Book(
  "The Fellowship of the Ring",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

const theTwoTowers = new Book(
  "The Two Towers",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

const bookTitles = Book.getTitles(fellowshipOfTheRing, theTwoTowers);

console.log(bookTitles.join(", ")); // The Fellowship of the Ring, The Two Towers
function Book(title, series, author) {
  this.title = title;
  this.series = series;
  this.author = author;
}

// Static methods are defined
// directly on the constructor function.
Book.getTitles = function (...books) {
  return books.map((book) => book.title);
};

// Instance methods are defined
// on the constructor function's `prototype` property.
Book.prototype.getInformation = function () {
  return `${this.title} by ${this.author}`;
};

const fellowshipOfTheRing = new Book(
  "The Fellowship of the Ring",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

const theTwoTowers = new Book(
  "The Two Towers",
  "The Lord of the Rings",
  "J.R.R. Tolkien"
);

console.log(fellowshipOfTheRing.getInformation()); // The Fellowship of the Ring by J.R.R. Tolkien

console.log(theTwoTowers.getInformation()); // The Two Towers by J.R.R. Tolkien

// Call the static `Book.getTitles()` method
// to get an array of the book titles.
const bookTitles = Book.getTitles(fellowshipOfTheRing, theTwoTowers);

console.log(bookTitles.join(", ")); // The Fellowship of the Ring, The Two Towers

Comparing Classes to Constructor Functions

ES2015 Classes are essentially syntactic sugar over traditional constructor functions and prototypes.


Javascript Inheritance

class CatalogItem {
  constructor(title, series) {
    this.title = title;
    this.series = series;
  }

  getInformation() {
    if (this.series) {
      return `${this.title} (${this.series})`;
    } else {
      return this.title;
    }
  }
}

class Book extends CatalogItem {
  constructor(title, series, author) {
    super(title, series);
    this.author = author;
  }
}

class Movie extends CatalogItem {
  constructor(title, series, director) {
    super(title, series);
    this.director = director;
  }
}

const theGrapesOfWrath = new Book(
  "The Grapes of Wrath",
  null,
  "John Steinbeck"
);
const aNewHope = new Movie(
  "Episode 4: A New Hope",
  "Star Wars",
  "George Lucas"
);

console.log(theGrapesOfWrath.getInformation()); // The Grapes of Wrath
console.log(aNewHope.getInformation()); // Episode 4: A New Hope (Star Wars)
console.log(Catalogitem instanceof Function); // true
console.log(Book instanceof Function); // true

Overriding a method in a parent class

class Movie extends CatalogItem {
  constructor(title, series, director) {
    super(title, series);
    this.director = director;
  }

  getInformation() {
    let result = super.getInformation();

    if (this.director) {
      result += ` [directed by ${this.director}]`;
    }

    return result;
  }
}

Javascript Modules

Introducing Node.js modules