ES6, ES2015: Classes

Classes introduced by ES2015 are just some syntax sugar. They don't really bring anything. That said, this can helps to improve code readability and make the code more accessible.

#Class declaration

Forget functions and prototypes, semantic is taking the relay as you will see in the following example:

class User {
  constructor(firstname, lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
  }

  sayName() {
    return `${this.firstname} ${this.lastname}`;
  }
}

// instantiation
const user = new User("John", "Doe");

// call of the method sayName()
console.log(user.sayName()); // John Doe

As a reminder, here is one way to code this class in ES5:

function User(firstname, lastname) {
  if (!(this instanceof User)) {
    throw new TypeError("Class constructors cannot be invoked without 'new'");
  }
  this.firstname = firstname;
  this.lastname = lastname;
}

User.prototype.sayName = function() {
  return this.firstname + " " + this.lastname;
};

// instantiation
var user = new User("John", "Doe");

// call of the method sayName()
console.log(user.sayName()); // John Doe

#Syntax

All methods should be written as simple function inside the class. You might denote the nice way to write getter and setter:

class User {
  constructor(firstname, lastname, type) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.type = type;
  }

  // method
  sayName() {
    return `${this.firstname}  ${this.lastname}`;
  }

  // getter
  get role() {
    return this.type;
  }

  // setter
  set role(value) {
    return (this.type = value);
  }
}

// the `new` is mandatory to instantiate a class
const user = new User("John", "Doe", "Contributor");

console.log(user.sayName()); // John Doe
console.log(user.role); // Contributor
user.role = "owner";
console.log(user.role); // Owner

#Inheritance

In order to have a class that inherits from another, we have the extends keyword.

Here is the an example:

class Contributor extends User {
  constructor(firstname, lastname, numberCommit) {
    // keyword `super` is used to call the constructor of the parent class
    super(firstname, lastname);
    this.numberCommit = numberCommit;
  }

  sayNameWithCommit() {
    // we can can also use `super` to call a method of the parent class
    return super.sayName() + " " + this.sayNumberCommit();
  }

  sayNumberCommit() {
    return this.numberCommit;
  }
}

const contributor = new Contributor("Jane", "Smith", 10);

console.log(contributor.sayName());
console.log(contributor.sayNumberCommit());

Reminder: prefer inheritance to composition.

#That's it

As you saw, all what you can do know was already possible before.

We just have a more readable code that should be more easily maintainable.

For now, you will need to use a transpiler like babel to be able to use classes.

One last thing: the bodies of class declarations and class expressions are executed in strict mode.

/* Initial strict mode */
class MyClass {
  someMethod() {
    /* Here we are in strict mode */
  }
}
/* Still the initial strict mode */