ES6 Classes vs. Constructor Functions

tl;dr

  • A constructor function is just a normal function that creates (constructs) an object
  • JavaScript does not has classes and hence it does not has methods. What you have are properties in an object, some of which may be functions
  • Javascript is not your classic class-based language but rather a prototype-based language.
  • Classes in JavasScript are syntactic sugar, meaning they’re a feature that only changes how you type something, but nothing changes under the hood.
  • The class syntax makes writing and building objects easier/neat.
'use strict'; // older version of Nodejs only allowed classes in Strcit mode

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

  // adding stuff to prototype to pass on to all instances of this class
  // any methods that exist in the class will be automatically added to the prototype
  greet() {
    return `Hello ${this.firstName} ${this.lastName}`
  }

  details() {
	  return `${this.firstName} ${this.lastName} is ${this.age} year(s) old`
  }
}

let jane = new Person('Jane', 'Davis', 28)

// test
console.info(jane) // Person { firstName: 'Jane', lastName: 'Davis', age: 28 }
console.info(jane.greet) // [Function: greet]
console.info(jane.greet()) // Hello Jane Davis

console.info(jane.__proto__) // Person {}
console.info(Object.getPrototypeOf(jane)) // Person {}

// Get all methods/functions inside the class
console.info(Object.getOwnPropertyNames(Person.prototype)) // [ 'constructor', 'greet', 'details' ]

console.info(Person) // [Function: Person]
console.info(jane.constructor) // [Function: Person]

is functionally equivalent to

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

// adding stuff to prototype to pass on to all instances of this class
Person.prototype.greet = function() {
  return `Hello ${this.firstName} ${this.lastName}`
}

Person.prototype.details = function() {
  return `${this.firstName} ${this.lastName} is ${this.age} year(s) old`
}

let jane = new Person('Jane', 'Davis', 28)

// test
console.info(jane) // Person { firstName: 'Jane', lastName: 'Davis', age: 28 }
console.info(jane.greet) // [Function]
console.info(jane.greet()) // Hello Jane Davis

console.info(jane.__proto__) // Person { greet: [Function], details: [Function] }
console.info(Object.getPrototypeOf(jane)) // Person { greet: [Function], details: [Function] }

console.info(Person) // [Function: Person]

Note that while jane.__proto__ in a normal constructor function gives us details for everything on the prototype Person { greet: [Function], details: [Function] }, jane.__proto__ in a class constructor only gives the class Person {}, not methods. Technically, there are no methods in JavaScript.

Notice that since classes are just syntactic sugar, there is no easy way of finding all (prototype) methods in a class. You can however use Object.getOwnPropertyNames(Foo.prototype) to find all properties in a class prototype.