Welcome to Part V of Learn ES6 The Dope Way, a series created to help you easily understand ES6 (ECMAScript 6)!

Today we’ll explore ES6 classes, learn how to compile our code into ES5 for browser compatibility and learn about some awesome resources that will help us understand ES6 in greater depth! Adventure time! ❤

1*EwyGlROHPNaLRBejoGqM3g

Classes in ES6

Benefits:

  • A simpler way of dealing with JavaScript’s Prototype-Inheritance — it’s just ‘syntactical sugar’.
  • You are still using the same object-oriented inheritance model.
  • Similar to class syntax in Java, Python, Ruby and PHP.
  • Saves you a lot of typing.

Beware:

  • Use can only invoke a class via new, not a function call.
  • Use super() to call the constructor of a parent class.
  • A class looks like an object but behaves like a function — because it is a function.
  • Class declarations are not hoisted as function declarations are.
  • A name given to a class expression is only local to the class body.
  • A SyntaxError will be thrown if the class contains more than one occurrence of a constructor method.
  • While the members of an object literal are separated by commas, commas are illegal in classes — this emphasizes the difference between them. Semicolons are only allowed for future syntax (possibly ES7), which may include properties cancelled by semicolons.
  • In derived classes(explained later), super() must be called first, before you can use the this keyword. Otherwise it will cause a ReferenceError.
  • Static properties are properties of the class itself. Thus while they can be inherited and accessed by directly calling the class name, if you call an instance of the class(and store it within a variable) you will not be able to access it with that variable.

Creating a Class

So how do we create a class? Let us first review how objects are created in ES5 without the use of classes:

function Bunny(name, age, favoriteFood) {
  this.name = name;
  this.age = age;
  this.favoriteFood = favoriteFood;
}
  
Bunny.prototype.eatFavFood = function () {
  console.log('\"Mmmm! Those ' + this.favoriteFood + ' were delicious\", said ' + this.name + ', the ' + this.age + ' year old bunny.');
};

var newBunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
newBunny.eatFavFood();
// "Mmmm! Those Raspberry Leaves were delicious", said Brigadier Fluffkins, the 3 year old bunny.

Now observe the same thing with ES6 classes:

class Bunny {
  constructor(name, age, favoriteFood){
    this.name = name;
    this.age = age;
    this.favoriteFood = favoriteFood;
  }
  
  eatFavFood() {
    console.log(`"Mmmm! Those ${this.favoriteFood} were delicious", said ${this.name} the ${this.age} year old bunny.`);
  };
}

let es6Bunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
es6Bunny.eatFavFood();
// "Mmmm! Those Raspberry Leaves were delicious", said Brigadier Fluffkins the 3 year old bunny.

What are the main differences? Clearly the class syntax looks like an object, but remember that actually it’s still a function and behaves so. Test it out yourself:

typeof Bunny
// function

Another main difference is anything you want to store must be within a constructor method. Any prototype method of the class should be inside of that class, but outside of the constructor, without writing ‘.prototype’, and in ES6 function syntax.

Twos Ways of Defining a Class & Prototype Inheritance

Now there are two main ways of defining a class — the example above is one of the more common ways, a class declaration. While a class is indeed a function and function declarations are hoisted — meaning the function can be accessed no matter if it is called before it is declared — yet you cannot hoist a class declaration. This is important to remember:

// Normal function declaration
// called before it is declared and it works.
callMe(); // Testing, Testing.

function callMe() {
  console.log("Testing, Testing.")
}

// This is called after, as we would do in a function expression,
// and it works too!
callMe() // Testing, Testing.


// But with classes...You can't create an instance of a class 
// before creating it:
let es6Bunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
es6Bunny.eatFavFood();

class Bunny {
  constructor(name, age, favoriteFood){
    this.name = name;
    this.age = age;
    this.favoriteFood = favoriteFood;
  }
  
  eatFavFood() {
    console.log(`"Mmmm! Those ${this.favoriteFood} were delicious", said ${this.name} the ${this.age} year old bunny.`);
  };
}

// Instead we get this: Uncaught ReferenceError: Bunny is not defined

The reason for this limitation is that classes can have an extends clause — used for inheritance — whose value can be specified at a later time or may even depend on an inputted value or computation. Since expressions may sometime need to be evaluated another time, it makes sense for this evaluation not to be hoisted before all values are evaluated. Not doing so may cause errors in your code.

Still, it is possible to store an instance of a class before it is created in a function for later use and evaluate it after the class has been defined:

function createNewBunny() { new Bunny(); }
createNewBunny(); // ReferenceError

class Bunny {...etc}
createNewBunny(); // Works!

The second way to define a class is a class expression. As with function expressions, class expressions can be named or anonymous. Be aware, these names are only local to the class body and cannot be accessed outside of it:

// anonymous:
const Bunny = class {
  etc...
};
const BunnyBurgerKins = new Bunny();

// named
const Bunny = class SurferBunny {
  whatIsMyName() {
    return SurferBunny.name;
  }
};
const BunnyBurgerKins = new Bunny();

console.log(BunnyBurgerKins.whatIsMyName()); // SurferBunny
console.log(SurferBunny.name); // ReferenceError: SurferBunny is not defined

There are two types of classes: The base class — or the parent class — and the derived class — the inherited subclass. Here Bunny is the base class and BelgianHare is the derived class since it has the extends clause. Notice how simple the syntax for prototype inheritance is with classes:

class Bunny {
  constructor(name, age, favoriteFood){
    this.name = name;
    this.age = age;
    this.favoriteFood = favoriteFood;
  }
  
  eatFavFood() {
    console.log(`"Mmmm! That ${this.favoriteFood} was delicious", said ${this.name} the ${this.age} year old bunny.`);
  };
}

class BelgianHare extends Bunny {
  constructor(favDrink, favoriteFood, name, age) {
    super(name, age, favoriteFood);
    this.favDrink = favDrink;
  }
  
  drinkFavDrink() {
    console.log(`\"Thank you for the ${this.favDrink} and ${this.favoriteFood}!\", said ${this.name} the happy ${this.age} year old Belgian Hare bunny.`)
  }
}

let newBelgHare = new BelgianHare('Water', 'Grass', 'Donald', 5);
newBelgHare.drinkFavDrink();
// "Thank you for the Water and Grass!", said Donald the happy 5 year old Belgian Hare bunny.
newBelgHare.eatFavFood();
// "Mmmm! That Grass was delicious", said Donald the 5 year old bunny.

The super() function inside of the derived class, BelgianHare, gives us access to the constructor in the base class, Bunny, so when we call the prototype methods from both classes(drinkFavDrink() from the derived class, and eatFavFood() from the base class), they both work!

Browser Compatibility

Not all ES6 features are fully supported on all browsers as of yet. In the meantime stay updated by checking out these sites:

Transpiling ES6 Code

Since not all browsers support all ES6 features you need to transpile your ES6 code into a compiler such as Babel or module bundler like Webpack.

Transpiling simply means taking out ES6 code and converting it into ES5 so it can be read by all browsers — like a safety precaution!

There are many transpiling tools, the most popular are also the ones that support the most ES6 features:

  • Babel.js
  • Closure
  • Traceur

You can use any of of these, but out of the three listed, I would recommend Babel for smaller projects. Please follow their simple steps for installing Babel into your project via Node: https://babeljs.io/

1*YHKpM73vm1u2fvrKgYcYYw

For larger projects I recommend using Webpack. Webpack does a lot of complicated things for you, including: transpiling code, SAS conversions, dependency management, and even replacing tools such as Grunt, Gulp and Browserify. There is already an informative tutorial written on Webpack right over here.

Resources

Check out these resources to learn and explore ES6 in greater depth:

1*h6QrITdqOjVWG9-e3nkLSA

The Mozilla Developer Network (MDN) is a superb tool for learning about all ES6 concepts, actually anything JavaScript. For example, let’s learn more about classes: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

Babel.js has super useful article summarizing all our ES6 points into one: https://babeljs.io/docs/learn-es2015/

This guy is always fun to watch: https://www.youtube.com/playlist?list=PL0zVEGEvSaeHJppaRLrqjeTPnCH6vw-sm

And check out this exhaustive list of ES6 study resources: https://github.com/ericdouglas/ES6-Learning

There are many, many more. Go forth my child, explore thy internet.

Remember, no matter how experienced you are — Google is your friend.

Congrats! You’ve made it through Learn ES6 The Dope Way Part V and now you’ve learned a clever way of using prototype inheritance through ES6 classes, understand that it’s important to always transpile your code since not all browsers support all features of ES6— either through Babel.js for smaller projects or Webpack for larger projects.

Keep your wisdom updated by liking and following. This is the last lesson in the Learn ES6 The Dope Way series! Congrats, you’ve made it!! Pat yourself in the back you did a great job!! I’m so proud of you! Yay!!!

1*2ecYe92TjNDCisDHLDH_4Q

Thanks for reading ❤ Stay tuned for more JavaScript lessons underway!

Part I: const, let & var

Part II: (Arrow) => functions and ‘this’ keyword

Part III: Template Literals, Spread Operators & Generators!

Part IV: Default Parameters, Destructuring Assignment, and a new ES6 method!

Part V: Classes, Transpiling ES6 Code & More Resources!

You can also find me on github ❤ https://github.com/Mashadim