Migrating to ES6 classes

Last week I wrote a short post about using ES6 arrow function.

Today I would love to talk about ES6 classes, what is brings onto the table, and why you should or shouldn’t be concerned.

ES6 Classes

var Car = function (number_of_wheels, number_of_doors) { 
this.number_of_wheels = number_of_wheels;
this.number_of_doors = number_of_doors
}
Car.prototype.getCarInfo = function () {
return this.number_of_wheels + ' wheels, ' + this.number_of_doors + ' doors.';
}
var car = new Car(4,4)
car.getCarInfo() // 4 wheels, 4 doors.

If you’ve ever done the above code before. That’s one way we used to create javascript classes using the prototype method. The below implementation stands as well.

// A callcheck for making sure class is not called as a function 
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Car = function () {
function Car(number_of_wheels, number_of_doors) {
_classCallCheck(this, Car);

this.number_of_wheels = number_of_wheels;
this.number_of_doors = number_of_doors;
}
  Car.prototype.getCarInfo = function getCarInfo() {
return this.number_of_wheels + ' wheels, ' + this.number_of_doors + ' doors.';
};
  return Car;
}();
var car = new Car(2, 2);
console.log(car.getCarInfo());

I’m not advocating you to continue using this or stop using it. But this is just to give a brief overview of what we were used to before ES6 classes. 
Now ES6 provides a more intuitive way of defining your object classes

For the same “Car” class created above let’s try and look at how it looks in ES6

class Car {
constructor(number_of_wheels, number_of_doors) {
this.number_of_wheels = number_of_wheels;
this.number_of_doors = number_of_doors;
}
  getCarInfo() {
return this.number_of_wheels + ' wheels, ' + this.number_of_doors + ' doors.';
}
}
let car = new Car(2,2);
console.log(car.getCarInfo());

If you’ve worked with other languages like Java, python, and C++. This won’t be as confusing as the previous examples above, which leverages on the ‘this’ keyword, using ‘javascript function’, and the ‘prototype method’. The new way makes use of the ‘class keyword’ and the ‘constructor function’.

http://www.itutslive.com/java-tutorials/inheritance-in-java/

Inherited Classes

Inheritance is the ability to pass on 
This is inheritance in ES5

var Tesla = function(number_of_wheels, number_of_doors, battery_size) {
Car.call(this, number_of_wheels, number_of_doors);
this.battery_size = battery_size;
}
Tesla.prototype = Object.create(Car.prototype); Tesla.prototype.constructor = Tesla;

Looking into ES6 you get the clean intuitive way of writing this with the ‘extends’ keyword

class Tesla extends Car{
constructor(number_of_wheels, number_of_doors, battery_size) {
super(number_of_wheels, number_of_doors)
this.battery_size = battery_size
}
}
let tesla = new Tesla(4,2);
console.log(tesla.getCarInfo())

Accessing base methods

Let us say we want to alter the ‘getCarInfo’ method from the parent ‘Car’ class.

var Tesla = function(number_of_wheels, number_of_doors, battery_size) {
Car.call(this, number_of_wheels, number_of_doors);
this.battery_size = battery_size;
  Tesla.prototype.getCarInfo = function () {
return Car.prototype.getCarInfo.call(this) + " A Tesla model with " + this.battery_size + " batteries.";
};
}
Tesla.prototype = Object.create(Car.prototype); Tesla.prototype.constructor = Tesla;

In ES6 you can do this as shown in the example below.

class Tesla extends Car{
constructor(number_of_wheels, number_of_doors, battery_size) {
super(number_of_wheels, number_of_doors)
this.battery_size = battery_size
}
getCarInfo() {
return super.getCarInfo() + " A Tesla model with " + this.battery_size + " batteries."
}
}
let tesla = new Tesla(4,2);
console.log(tesla.getCarInfo())

Getters and Setters

To finish this off, I would love to talk about what ES6 brings on the table in terms of creating getters and setters.

Let’s say you have a private attribute within “Tesla”, called ‘weight’. Which you has a default value but would love to change for different models of future tesla cars. We can access and manipulate weight through the ‘set’ and ‘get’ keywords. 
Let’s explore how this is done in both ES5 and ES6.

In ES5

Tesla.prototype = {     
set weight (weight) { this._weight = weight; },
get weight () { return this._weight; }
};

In ES6

class Tesla extends Car{
constructor(number_of_wheels, number_of_doors, battery_size) {
super(number_of_wheels, number_of_doors)
this.battery_size = battery_size
this._weight = 100
}

getCarInfo() {
return super.getCarInfo() + " A Tesla model with " + this.battery_size + " batteries."
}

get weight () {
return this._weight
}

set weight (weight) {
this._weight = weight
}

}
let tesla = new Tesla(4,2, 5)
console.log("size", tesla.weight) // weight is 100
tesla.weight = 20
console.log("size", tesla.weight) // weight is now 20
Some few things to note here, once you set a getter for an attribute you’d need to also create a getter for the same attribute which has the same name. In our case we couldn’t have done away with the ‘set weight(weight)’ method.

There is more one can learn about inheritance in javascript classes. In this post gave a brief overview of classes, inheritance and a bit ES6 class gotchas. Please feel free to share, comment and give feedback.

You can find the above code here

Enjoy.